模板模板参数导致Clang下的编译器错误,但不会导致GCC

bar*_*top 7 c++ templates language-lawyer

在帮助解决模板模板参数太多模板参数中出现的问题时,我脑子里出现了一个问题:在这种情况下,哪个编译器对编译是正确的:

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;
}
Run Code Online (Sandbox Code Playgroud)

GCC 7+编译它没有错误.Clang 6及更高版本给出错误,表明Operator模板作为模板参数传递时出现问题:

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.
Run Code Online (Sandbox Code Playgroud)

显然,即使提供了默认的第三个参数,它也将其视为3参数模板.所以这是一个问题,哪个编译器是对的?标准是否对此类情况有所说明?

PS我不需要解决这些问题,因为它非常简单.我只是想知道"谁是对的"

son*_*yao 8

Gcc是对的.Clang似乎不符合C++ 17.

由于C++ 17(CWG 150),默认模板参数所允许的一个模板的模板参数以匹配具有较少模板参数模板的模板的参数.

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
Run Code Online (Sandbox Code Playgroud)

Operator有3个模板参数,第3个有默认值,然后它可以用作模板模板参数的参数Op,即使它只需要两个模板参数.