我遇到以下代表性示例代码的问题:
template<int I> struct X {}; template<int I> struct Y {}; template<int I> struct XX: X<I> {}; template<int I> struct YY: Y<I> {}; template<template<int> class TP> struct traits; template<> struct traits<X> { template<int I> using Tpl=XX<I>; }; template<> struct traits<Y> { template<int I> using Tpl=YY<I>; }; template<template<int> class TP> struct Z {}; template<template<int> class TP> struct W: Z<traits<TP>::Tpl> {}; int main() { Z<traits<X>::Tpl> zx; Z<traits<Y>::Tpl> zy; W<X> wx; W<Y> wy; return 1; }
此代码可以用ICC-19.0.0编译(似乎可以用MSVC-19.24编译),但不能用GCC-10.1,CLANG-10.0.0和ICC-18.0.0编译。
对于GCC-10.1,错误消息为:
<source>:32:28: error: type/value mismatch at argument 1 in template parameter list for 'template<template<int <anonymous> > class TP> struct Z'
32 | struct W: Z<traits<TP>::Tpl> {};
| ^
<source>:32:28: note: expected a class template, got 'traits<TP>::Tpl'
上下文:我有一个模板类Z
,它有一个template模板参数。 我想从中派生一个类w
,对于最终用户来说,它接受与z
(x
或y
)相同的模板模板参数,但将它们分派给内部类xx
和yy
,后者通过派生它们来修改x
和y
的行为。
这个问题是编译器bug吗? 如果是,是否有某种解决办法?
非常感谢!
您需要告诉编译器TPL
是一个模板:
template<template<int> class TP>
struct W: Z<traits<TP>::template Tpl> {};
// ^^
Afaik,没有任何改变,我可能是一些编译器是/已经对它更松懈,让你离开没有它。 需要它的原因与类型需要typeName
的原因类似:可能存在traits
的专门化,其中tpl
不是模板,因此您需要告诉编译器它确实是模板。