C++ 将默认参数作为arity较小的模板类参数的类模板处理不一致
以下代码段在C++17上被Clang拒绝,在C++17上被GCC接受,在C++14上被GCC拒绝。这与所有最新的编译器版本一致。正确的行为是什么C++ 将默认参数作为arity较小的模板类参数的类模板处理不一致,c++,templates,c++17,language-lawyer,template-meta-programming,C++,Templates,C++17,Language Lawyer,Template Meta Programming,以下代码段在C++17上被Clang拒绝,在C++17上被GCC接受,在C++14上被GCC拒绝。这与所有最新的编译器版本一致。正确的行为是什么 template <class T, class = int> struct test1 {}; template <class T, template <class> class> struct test2 {}; using test_t = test2<int, test1>; 模板 结构te
template <class T, class = int>
struct test1 {};
template <class T, template <class> class>
struct test2 {};
using test_t = test2<int, test1>;
模板
结构test1{};
模板
结构test2{};
使用test_t=test2;
编辑:显然这实际上是在Clang上实现的,它只需要一个明确的标志:
-frelaxed template-template-args
,在使用-pedantic
时不包括它,GCC是正确的行为。它与C++17中接受的一致
从论文的引言中可以看出:
模板参数仅绑定到匹配的参数
参数列表。匹配当前定义为精确匹配;每个
参数的参数列表中的模板参数必须具有相同的
种类和类型作为
模板参数的参数列表。(有一个不明智的建议
当参数包出现在
模板参数的参数列表;本文保留了
匹配规则排除了许多合理的参数。这
本文调整匹配规则以调用偏序来
确定模板参数何时为模板的有效匹配项
模板参数
本文还包含了将要更改的代码示例,这段代码与您观察到的示例非常相似:
template <template <typename> class> void FD();
template <typename, typename = int> struct SD { /* ... */ };
FD<SD>(); // OK; error before this paper (CWG 150)
模板void FD();
模板结构SD{/*…*/};
FD();//好啊本文前的错误(CWG 150)
@LiarokapisAlexandros-Clang报告自版本4起支持此功能。这可能是一个bug或回归。显然这实际上是在Clang上实现的,它只需要一个明确的标志:-frelaxed template-template-args
。不确定在使用-pedantic
时不包含此选项是否正确。@LiarokapisAlexandros-我相信clang开发人员担心这会破坏现有代码,因为重载解决方案现在的工作方式基本不同。在这一点上不能真的指责他们。但是一个信息性的诊断是很好的。在问题中包含失败案例中产生的错误消息可能是值得的。因为我找到了报告,我可以搜索更多关于这个问题的信息,结果发现这是重复的。