使用外部类的可变参数模板中的args部分特化可变参数模板内部类是否合法

W.F*_*.F. 13 c++ templates template-specialization variadic-templates c++11

考虑一下代码:

#include <iostream>

template <class... Ts>
struct outer {
   template <class... ITs>
   struct inner {
      static constexpr bool value = false;
   };

   template <class... ITs>
   struct inner<Ts..., ITs...> {   
      static constexpr bool value = true;
   };
};

int main() {
   std::cout << outer<int, float, double>::inner<int, float, double, int>::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

代码用clang ++编译但不用g ++编译产生错误:

temp3.cc:11:11:错误:参数包参数'Ts ...'必须位于模板参数列表的末尾

struct inner<Ts..., ITs...> {
       ^
Run Code Online (Sandbox Code Playgroud)

正如我已经在这里建立的那样,内部阶级的部分专业化应该是合法的.

编辑: 为了完整性,值得补充一点,上面代码的clang警告他可能在推导IT参数时遇到问题,但没有任何问题......

Bar*_*rry 8

这是一个gcc bug.这是一个完全有效的部分专业化:

template <class... ITs>
struct inner<Ts..., ITs...> {   
   static constexpr bool value = true;
};
Run Code Online (Sandbox Code Playgroud)

推导出的模板参数包必须是最后一个,并且ITs...满足要求.但这Ts...不是一个需要在这里推断的包,它只是一个特定的参数包.

此外,gcc编译了几个等效的配方:

template <class... Ts>
struct X {
    template <class... Us>
    static void foo(Ts..., Us...) { }
};

int main() {
   X<int>::foo(1, 'c');
}
Run Code Online (Sandbox Code Playgroud)

和:

template <class... Us>
struct A { };

template <class... Ts>
struct X {
    template <class... Us>
    static void foo(A<Ts..., Us...>) { }
};

int main() {
   X<int>::foo(A<int, char>{});
}
Run Code Online (Sandbox Code Playgroud)

这些与您的原始示例完全相同.

  • 我确实认为部分专业化是有效的,但我不确定所写的标准是否允许它.[14.5.5p8.5]说*如果参数是包扩展(14.5.3),它应该是模板参数列表*中的最后一个参数.这是部分特化的特定要求,因此它不适用于您的示例.对于我来说,这看起来更像是标准问题而不是编译器错误. (4认同)