内部模板的递归特化结束 class

End of recursion specialization of inner template class

考虑这个工作代码:

#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<> 是一个不完整的类型。但是我定义了。

[temp.expl.spec]/p15 禁止显式特化成员模板而不显式特化每个封闭模板:

A member or a member template may be nested within many enclosing class templates. In an explicit specialization for such a member, the member declaration shall be preceded by a template<> for each enclosing class template that is explicitly specialized. [ Example:

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();

— end example ]

例如,这段代码编译:

template <>
template <>
struct A<>::B<> {
    static void execute() {}  // End of recursion
};

但它不允许您使用封闭的 class 模板中的模板参数。更好的方法是在主模板中使用包扩展 "trick":

template <typename... Ts>
template <typename... Args>
struct A<Ts...>::B {
    static void execute() {
        using unpack = int[];
        (void)unpack{((std::cout << typeid(Args).name() << ' '), 0)...};
    }
};