C++变参非类型模板参数场景下为何需要定义主模板?
问题解答
1. 核心原因:你的原始代码定义的是偏特化,而非主模板
你写的如下代码语法上属于类模板的偏特化定义,不是主模板定义:
#include <array> #include <type_traits> template<typename T, int head_size, int... tail_sizes> struct yarray<T, head_size, tail_sizes...> : public std::conditional_t<sizeof...(tail_sizes) == 0, std::array<T, head_size>, std::array<yarray<T, tail_sizes...>, head_size>> {};
C++标准明确要求:所有的偏特化、全特化都必须依附于一个已经提前声明的主模板存在,不能独立定义。没有主模板的情况下,编译器根本不知道yarray是一个类模板,也无法识别你写的<T, head_size, tail_sizes...>后缀对应的模板参数规则,所以直接抛出yarray is not a class template的编译错误。这是语法层面的硬性要求,和你后续的递归逻辑会不会用到空参数包实例没有关系。
2. 关于“递归不会触碰空变参包”的误区
你代码里的递归逻辑确实在tail_sizes为空时会终止,不会实例化参数为空的yarray<T>,因此你提供的空主模板永远不会被实际实例化使用。但这不代表主模板可以省略:编译器处理模板的顺序是先识别主模板的参数规则,再匹配对应的偏特化实现,哪怕主模板本身永远不会被实例化,它的声明是编译器识别后续偏特化的必要前提。
举个更简单的同类例子:如果你想写一个针对int类型的模板特化,必须先声明主模板,否则代码直接语法错误:
// 必须先有主模板声明,下面的特化才合法 template<typename T> struct A; // 偏特化/全特化不能脱离主模板存在 template<> struct A<int> { int val; };
你遇到的问题和上面这个例子的本质完全一致。
内容的提问来源于stack exchange,提问作者NoSenseEtAl
相关产品推荐
相关产品推荐

