class 模板与默认参数作为模板模板 class 更小参数的不一致处理

inconsistent treatment of class template with defaulted argument as template template class argument of smaller arity

以下代码段在 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>;

编辑:显然这实际上是在 Clang 上实现的,它只需要一个显式标志:-frelaxed-template-template-args 使用 -pedantic.

时不包括在内

GCC 的 正确的行为。它与被 C++17 接受的 p0522r0 一致。

来自论文的介绍:

Template template-parameters only bind to arguments with matching parameter lists. Matching is currently defined as an exact match; each template parameter in the argument's parameter list must have the same kind and type as the corresponding parameter in the template-parameter's parameter list. (There is an ill-advised exception to this rule when a parameter pack appears in the template-parameter's parameter list; this paper preserves that special behavior.) The matching rules exclude many reasonable arguments. This paper adjusts the matching rules to invoke partial ordering to determine when a template template-argument is a valid match for a template-parameter.

该论文还包含将发生变化的代码示例,此代码段与您观察到其行为的示例非常相似:

template <template <typename> class> void FD();
template <typename, typename = int> struct SD { /* ... */ };
FD<SD>();  // OK; error before this paper (CWG 150)