提问者:小点点

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


我遇到以下代表性示例代码的问题:

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(xy)相同的模板模板参数,但将它们分派给内部类xxyy,后者通过派生它们来修改xy的行为。

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

非常感谢!


共1个答案

匿名用户

您需要告诉编译器TPL是一个模板:

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

Afaik,没有任何改变,我可能是一些编译器是/已经对它更松懈,让你离开没有它。 需要它的原因与类型需要typeName的原因类似:可能存在traits的专门化,其中tpl不是模板,因此您需要告诉编译器它确实是模板。