C++ 中允许 "conversion" 个模板模板参数?

What "conversion" of template template parameters is allowed in C++?

我试图了解在什么情况下我可以将类型模板作为参数传递给具有不同签名的模板模板参数。例如,我希望以下内容可以成功编译。

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), templates taking parameter pack like foo, should be allowed to be specified as template template argument for bar 甚至它需要一个模板参数。

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