Template template argument causes compiler error u

2020-07-09 08:27发布

While helping with problem noted in too many template parameters in template template argument a question arose in my head: which compiler is right about the compilation in this case:

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;
}

GCC 7+ compiles it with no errors. Clang 6 and later gives errors showing that there is a problem with Operator template passed as template argument:

tmp.cpp:19:35: error: template argument has different template parameters than its corresponding 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.

Obviously, it treats it as 3-arguments template even though the default third argument is supplied. So here is the question, which of the compilers is right? Does standard say anything about such situations?

PS I do not need a workaround for these kinds of problems as it is pretty simple. I just want to know "who is right"

1条回答
2楼-- · 2020-07-09 09:04

Gcc is correct. Clang seems not in accordance with C++17.

Since C++17 (CWG 150), the default template arguments are allowed for a template template argument to match a template template parameter with fewer template parameters.

template<class T> class A { /* ... */ };
template<class T, class U = T> class B { /* ... */ };
template <class ...Types> class C { /* ... */ };

template<template<class> class P> class X { /* ... */ };
X<A> xa; // OK
X<B> xb; // OK in C++17 after CWG 150
         // Error earlier: not an exact match
X<C> xc; // OK in C++17 after CWG 150
         // Error earlier: not an exact match

Operator has 3 template parameters, the 3rd one has default value, then it could be used as the argument for template template parameter Op, even it only expects two template parameters.

查看更多
登录 后发表回答