C++递归模板推导机制解析及相关技术与标准咨询
递归模板类相关问题解答
代码示例
#include <iostream> template<typename X = char, class T = int> class ABC; template<class X, class T> class ABC <X, ABC<X, T>>{ public: T t; }; template<class T, class M> class ABC : public ABC<T, ABC<T,M>> {}; int main() { ABC<int, char> abc; abc.t = 1; ABC<> abcd; abcd.t = 3; std::cout << abc.t << " " << abcd.t << std::endl; }
运行输出:
3
编译环境:Ubuntu20 附带 GCC 9.4.0,编译参数 -std=c++17
问题与解答
1. 这段代码的模板推导具体是如何工作的?
- 声明
ABC<int, char> abc时:- 首先匹配主模板
template<class T, class M> class ABC(主模板参数T=int、M=char,与前置声明的参数顺序对应),它继承自ABC<T, ABC<T,M>>,也就是ABC<int, ABC<int, char>>。 ABC<int, ABC<int, char>>会匹配偏特化模板template<class X, class T> class ABC <X, ABC<X, T>>:这里X=int,T=char,该偏特化明确定义了成员T t(即char t)。
- 首先匹配主模板
- 声明
ABC<> abcd时:- 触发前置声明的默认参数:
X=char,T=int,实际类型为ABC<char, int>,匹配主模板后继承自ABC<char, ABC<char, int>>。 - 这个继承的基类匹配偏特化,此时偏特化里的
T=int,因此成员t是int类型。
- 触发前置声明的默认参数:
2. 该示例所使用的编程技术是什么?
这是类模板偏特化结合递归模板继承的技术,属于模板元编程的基础技巧。通过偏特化的匹配规则,让递归继承的链条最终终止在有具体实现的偏特化版本上。
3. 能否提供相关的C++标准资料?
- C++17 标准中类模板偏特化章节:17.5.5 Class template partial specializations
- 模板实参推导章节:17.8.2 Template argument deduction
- 递归模板实例化终止规则:标准规定模板实例化时会优先匹配偏特化版本,以此避免无限递归,属于模板实例化的重载解析范畴(17.5.5.1 Matching of partial specializations)
4. 代码中ABC<T,M>继承自ABC<T, ABC<T,M>>属于自引用模板类,其推导如何终止?为何仅声明主模板却能运行?
- 递归终止原因:主模板继承的
ABC<T, ABC<T,M>>恰好符合偏特化模板的匹配模式ABC<X, ABC<X, T>>,编译器实例化时会优先选择偏特化版本,而偏特化没有继续递归继承,因此递归链条在这里终止。 - 主模板仅声明可运行的原因:主模板本身仅作为中间层,通过继承获取了偏特化基类的成员,我们访问的
t是基类(偏特化)的成员,主模板不需要自己定义额外成员就能正常使用。
5. 运行时abc.t输出不可见字符,仅显示空格和3,该现象如何解释?
abc 的类型是 ABC<int, char>,对应的 t 是 char 类型。你给 abc.t = 1,相当于赋值了 ASCII 码为1的字符,该字符是标题开始(SOH),属于不可见的控制字符,输出时不会显示任何可见内容。而 abcd.t 是 int 类型的3,输出正常,所以最终视觉上看到的是不可见字符占据的位置(类似空格)加上3,即输出的 3。
内容的提问来源于stack exchange,提问作者Jerry2102
相关产品推荐
相关产品推荐

