推导类型能否作非类型模板实参?StringLiteral省略N的原因
C++模板相关问题解答
1. 推导类型能否用作非类型模板形参的类型?
在C20及更高版本中,推导类型(比如auto或带约束的推导类型)可以用作非类型模板形参的类型,但有个关键前提:推导出来的实际类型必须属于C标准允许的非类型模板形参合法类型集合。
合法类型包括:整数类型、枚举类型、指针、引用、std::nullptr_t,以及C++20新增的字面类(满足特定constexpr要求的类)等。比如:
// 合法:auto推导N为int,属于合法非类型形参类型 template<auto N> struct NumHolder { static constexpr auto value = N; }; // 调用时推导N的类型为int NumHolder<42> nh;
如果推导出来的类型不合法(比如std::string这类非字面类型),编译器会直接报错,因为这类类型无法作为非类型模板形参。
2. 为何声明template<StringLiteral lit>时可省略StringLiteral的size_t N模板参数?
这是C++20的类模板实参推导(CTAD)和字面类作为非类型模板形参两个特性结合的结果:
- 字面类资格:代码中的
StringLiteral是一个字面类——它拥有constexpr构造函数,成员value是字面类型的数组,完全符合C++20对非类型模板形参的字面类要求,因此可以直接作为非类型模板形参的类型。 - 自动推导模板参数:当你传入字符串字面量(比如
Print<"test">())时,编译器会用这个字符串字面量(类型为const char[5])触发类模板实参推导,自动算出StringLiteral的模板参数N为5,实例化出StringLiteral<5>的对象,再把这个对象作为非类型模板形参传给Print模板。
简单说,编译器会帮你完成N的推导工作,不需要显式写出template<StringLiteral<N> lit>。
内容的提问来源于stack exchange,提问作者Petr
相关产品推荐
相关产品推荐

