模板模板参数和模板别名:编译器错误?
Template template parameter and template alias: compiler bug?
我对以下代表性示例代码有疑问:
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'
上下文:我有一个模板 class Z
,它有一个模板模板参数。我想从中派生一个 class,W
,最终用户接受与 Z
(X
或 Y
)相同的模板模板参数,但将它们分派给内部 classes XX
和 YY
,这通过从它们派生来修改 X
和 Y
的行为。
这个问题是编译器错误吗?如果是,是否有某种解决方法?
非常感谢!
你需要告诉编译器Tpl
是一个模板:
template<template<int> class TP>
struct W: Z<traits<TP>::template Tpl> {};
// ^^
Afaik,这没有任何改变,我可能是一些编译器/已经对此更加宽松,让你不用它就可以逃脱。
需要它的原因类似于类型需要 typename
的原因:可能有 traits
的特化,其中 Tpl
不是模板,因此您需要告诉编译器它确实是一个。
我对以下代表性示例代码有疑问:
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'
上下文:我有一个模板 class Z
,它有一个模板模板参数。我想从中派生一个 class,W
,最终用户接受与 Z
(X
或 Y
)相同的模板模板参数,但将它们分派给内部 classes XX
和 YY
,这通过从它们派生来修改 X
和 Y
的行为。
这个问题是编译器错误吗?如果是,是否有某种解决方法?
非常感谢!
你需要告诉编译器Tpl
是一个模板:
template<template<int> class TP>
struct W: Z<traits<TP>::template Tpl> {};
// ^^
Afaik,这没有任何改变,我可能是一些编译器/已经对此更加宽松,让你不用它就可以逃脱。
需要它的原因类似于类型需要 typename
的原因:可能有 traits
的特化,其中 Tpl
不是模板,因此您需要告诉编译器它确实是一个。