1

I'm trying to implement some template template code as the following, it work well on GCC 7, but failed to compile on Clang 6. Any ideas?

#include <iostream>

template <template <typename, typename> class Op>
class Function
{
};

template <typename A, typename B, bool is_f = std::is_floating_point<A>::value || std::is_floating_point<B>::value > struct Operator;

template <typename A, typename B>
struct Operator<A, B, false>
{};


template <typename A, typename B>
struct Operator<A, B, true>
{};

using FunctionOperator = Function<Operator>;


int main(int argc, char * argv[]){
    std::cout << "hi!\n";
    return 0;
}

Compile errors:

tmp.cpp:19:35: error: template template argument has different template parameters than its corresponding template template parameter
using FunctionOperator = Function<Operator>;
                                  ^
tmp.cpp:8:1: note: too many template parameters in template template argument
template <typename A, typename B, bool is_f = std::is_floating_point<A>::value || std::is_floating_point<B>::value > struct Operator;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tmp.cpp:3:11: note: previous template template parameter is here
template <template <typename, typename> class Op>
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
flowyi
  • 81
  • 1
  • 6

1 Answers1

2

Clang clearly has problem with fact that the basic Operator struct template has 3 not 2 arguments and thus refuses to accept it inside Function template. According to answer to this question Template template argument causes compiler error under Clang but not GCC Clang is wrong and GCC is standard compliant in this issue. Anyway here's a quick workaround for this issue:

template <template <typename, typename> class Op>
class Function
{
};

template <typename A, typename B, bool is_f = std::is_floating_point<A>::value || std::is_floating_point<B>::value > struct Operator;

template <typename A, typename B>
struct Operator<A, B, false>
{};


template <typename A, typename B>
struct Operator<A, B, true>
{};

template<class A, class B>
using Op = Operator<A, B>;

using FunctionOperator = Function<Op>;


int main(int argc, char * argv[]){
    FunctionOperator o;
    std::cout << "hi!\n";
    return 0;
}

It works both with gcc and clang.

bartop
  • 9,971
  • 1
  • 23
  • 54