模板模板参数和模板别名:编译器错误?

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,最终用户接受与 ZXY)相同的模板模板参数,但将它们分派给内部 classes XXYY,这通过从它们派生来修改 XY 的行为。

这个问题是编译器错误吗?如果是,是否有某种解决方法?

非常感谢!

你需要告诉编译器Tpl是一个模板:

template<template<int> class TP>
struct W: Z<traits<TP>::template Tpl> {};
                   // ^^      

Afaik,这没有任何改变,我可能是一些编译器/已经对此更加宽松,让你不用它就可以逃脱。 需要它的原因类似于类型需要 typename 的原因:可能有 traits 的特化,其中 Tpl 不是模板,因此您需要告诉编译器它确实是一个。