问题描述
我试图了解在什么情况下我可以将类型模板作为具有不同签名的模板模板参数的参数传递。例如,我希望以下内容可以成功编译。
template <typename...>
struct foo { };
template <template <typename> typename Template>
struct bar { };
using quux = bar<foo>;
毕竟,bar
要求的模板只接受一种类型的模板参数,而我给了它一个。但是对于 Clang 11.0.1,这不能编译。
好的,好的。当然,如果这是不允许的,那么以下内容也应该被禁止。
template <typename>
struct foo { };
template <template <typename...> typename Template>
struct bar { };
using quux = bar<foo>;
这里的 bar
要求一个可以接受任意数量类型模板参数的模板,我不给它一个。然而 Clang 接受了这一点! (当然,如果我在 bar
中编写代码来实例化 Template
,模板参数与 foo
的签名不匹配,它仍然会失败。)
这在我看来是倒退的。它允许将更具体的模板签名转换为更通用的签名,而不是相反。
我也尝试过使用 GCC 10.2.0。 GCC 接受两者。哈哈。
我正在使用 -Wall -Wextra -O0 -std=c++20 -pedantic
与两个编译器一起编译。
标准是否真的没有说明上面的第一个例子是否格式错误,或者至少有一个编译器不符合标准?
而且,无论标准要求什么,为什么 Clang 会在这里做出选择?这对我来说似乎是一个错误。
解决方法
我认为 Clang 是错误的。由于 C++17 (P0522R0,CWG 150),采用 foo
之类的参数包的模板,应该允许将 bar
指定为 template template argument,即使它需要一个模板参数。
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