模板模板参数和默认值
Template template parameter and default values
考虑以下代码:
template<typename T>
struct A { };
// same as A, but with one extra defaulted parameter
template<typename T, typename F = int>
struct B { };
template<template<typename> typename T>
T<int> build() { return {}; }
int main()
{
build<A>(); // works in gcc and clang
build<B>(); // works in gcc, does not work in clang
}
g++ (7.3.0) 编译代码很好,但是,clang++ (5.0.1) 发出以下内容:
example.cpp:14:5: error: no matching function for call to 'build'
build<B>(); // works in gcc, does not work in clang
^~~~~~~~
example.cpp:9:8: note: candidate template ignored: invalid
explicitly-specified argument for template parameter 'T'
T<int> build() { return {}; }
哪个编译器是正确的?
注:
重要的一行显然是:
template<template<typename> typename T>
因为两个编译器都满意:
template<template<typename...> typename T>
所以问题是在传递模板模板参数时是否应该考虑默认值。
据我所知,你的代码从C++17开始是正确的,之前是错误的。
根据 P0522R0,这是新标准的一部分,我看到一个与您的代码非常非常相似的示例(参见 "overview"):
template <template <typename> class> void FD();
template <typename, typename = int> struct SD { /* ... */ };
FD<SD>(); // OK; error before this paper (CWG 150)
根据 compiler support tables in ccpreference,g++ 从版本 7 开始支持 P0522R0,从版本 4 开始支持 clang++。因此两个编译器都应该支持您的代码。
但是查看 this page 中的 table,定义了对 llvm (clang) 5 的支持 "partial",并且根据注释,
(12): Despite being the the resolution to a Defect Report, this feature is disabled by default in all language versions, and can be enabled explicitly with the flag -frelaxed-template-template-args in Clang 4 onwards. The change to the standard lacks a corresponding change for template partial ordering, resulting in ambiguity errors for reasonable and previously-valid code. This issue is expected to be rectified soon.
因此,冒着风险,您可以尝试使用标志 -frelaxed-template-template-args
。
考虑以下代码:
template<typename T>
struct A { };
// same as A, but with one extra defaulted parameter
template<typename T, typename F = int>
struct B { };
template<template<typename> typename T>
T<int> build() { return {}; }
int main()
{
build<A>(); // works in gcc and clang
build<B>(); // works in gcc, does not work in clang
}
g++ (7.3.0) 编译代码很好,但是,clang++ (5.0.1) 发出以下内容:
example.cpp:14:5: error: no matching function for call to 'build'
build<B>(); // works in gcc, does not work in clang
^~~~~~~~
example.cpp:9:8: note: candidate template ignored: invalid
explicitly-specified argument for template parameter 'T'
T<int> build() { return {}; }
哪个编译器是正确的?
注: 重要的一行显然是:
template<template<typename> typename T>
因为两个编译器都满意:
template<template<typename...> typename T>
所以问题是在传递模板模板参数时是否应该考虑默认值。
据我所知,你的代码从C++17开始是正确的,之前是错误的。
根据 P0522R0,这是新标准的一部分,我看到一个与您的代码非常非常相似的示例(参见 "overview"):
template <template <typename> class> void FD();
template <typename, typename = int> struct SD { /* ... */ };
FD<SD>(); // OK; error before this paper (CWG 150)
根据 compiler support tables in ccpreference,g++ 从版本 7 开始支持 P0522R0,从版本 4 开始支持 clang++。因此两个编译器都应该支持您的代码。
但是查看 this page 中的 table,定义了对 llvm (clang) 5 的支持 "partial",并且根据注释,
(12): Despite being the the resolution to a Defect Report, this feature is disabled by default in all language versions, and can be enabled explicitly with the flag -frelaxed-template-template-args in Clang 4 onwards. The change to the standard lacks a corresponding change for template partial ordering, resulting in ambiguity errors for reasonable and previously-valid code. This issue is expected to be rectified soon.
因此,冒着风险,您可以尝试使用标志 -frelaxed-template-template-args
。