考虑这个有效的代码:
#include <typeinfo>
template <typename ...> struct A;
template <typename First, typename... Rest>
struct A<First, Rest...> {
static void execute() {
std::cout << typeid(First).name() << ' ';
A<Rest...>::execute();
}
};
template <>
struct A<> {
static void execute() {} // End of recursion.
};
int main() {
A<char, bool, int>::execute(); // char bool int
}
那么为什么下面的递归结束不能编译(注释中提供的错误语句):
#include <typeinfo>
template <typename ...> struct A;
template <typename... Ts>
struct A {
template <typename...> struct B;
template <typename...> static void execute();
};
template <typename... Ts>
template <typename First, typename... Rest>
struct A<Ts...>::B<First, Rest...> {
static void execute() {
std::cout << typeid(First).name() << ' ';
B<Rest...>::execute();
}
};
template <typename... Ts>
template <> // invalid explicit specialization before '>' token
struct A<Ts...>::B<> { // template parameters not used in partial specialization: Ts
static void execute() {} // End of recursion
};
template <typename... Ts>
template <typename... Us>
void A<Ts...>::execute() {
B<Ts..., Us...>::execute();
}
int main() {
A<char, bool, int>::execute<double, short, float>();
}
当我使用这个递归结束而不是上面时它确实有效:
template <typename... Ts>
template <typename Last>
struct A<Ts...>::B<Last> {
static void execute() {std::cout << typeid(Last).name();}
};
但我只是想知道原始尝试的错误。此外,我必须使用第二种方式重复执行execute()函数的主体(这当然会导致更多的维护责任)。
GCC 4.9.2指出A<char, bool, int>::B<>
是一种不完整的类型。但我定义了它。
答案 0 :(得分:2)
[temp.expl.spec] / p15禁止显式专门化成员模板,而不明确专门化每个封闭模板:
成员或成员模板可以嵌套在许多封闭的类模板中。在对这样一个成员的显式特化中,成员声明前面应该有一个
template<>
,用于明确专门化的每个封闭类模板。 [例如:template<class T1> class A { template<class T2> class B { void mf(); }; }; template<> template<> class A<int>::B<double>; template<> template<> void A<char>::B<char>::mf();
- 结束示例]
例如,此代码编译:
template <>
template <>
struct A<>::B<> {
static void execute() {} // End of recursion
};
但它不允许您使用封闭类模板中的模板参数。更好的方法是在主模板中使用包扩展“技巧”:
template <typename... Ts>
template <typename... Args>
struct A<Ts...>::B {
static void execute() {
using unpack = int[];
(void)unpack{((std::cout << typeid(Args).name() << ' '), 0)...};
}
};