C++自定义类作为非类型模板参数传入函数的实现方法
自定义类作为非类型模板参数的实现方法
原代码问题
初始实现无法编译,核心原因有3个:
- 类
C的定义位置晚于模板对C类型的引用,编译器解析template<C cc>时还未识别到C的类型定义 - 传入模板的
cc是main函数内定义的运行期局部变量,而非类型模板参数要求实参必须是编译期可确定的常量,这和int示例中直接传入常量100的要求一致 - C++20标准发布前,语言本身不支持直接将自定义类类型作为非类型模板参数按值传递,仅支持整型、枚举、指针/引用、空指针类型等有限的非类型参数类型。
正确实现
C++20及以上版本(原生支持类类型非类型模板参数)
C++20放宽了非类型模板参数的限制,只要自定义类是字面量类型、满足结构化比较要求(简单的公有成员聚合类默认满足),就可以直接像int一样作为非类型模板参数使用,写法和预期效果完全一致:
#include <iostream> using namespace std; // 类定义必须放在模板声明之前 class C { public: int l = 10; }; // 直接声明类类型的非类型模板参数 template<C cc> void A() { cout << cc.l << endl; } int main() { // 直接传入编译期构造的常量对象,和传入int常量写法一致 A<C{100}>(); // 也可以先定义constexpr编译期常量后传入 constexpr C cc{200}; A<cc>(); }
C++11/14/17版本(兼容实现)
旧标准不支持类类型按值作为非类型模板参数,可以通过传递静态存储期constexpr实例的const引用实现近似效果:
#include <iostream> using namespace std; class C { public: int l = 10; }; // 提前定义静态存储期的编译期常量实例 constexpr C c_val1{100}; constexpr C c_val2{200}; // 以const引用作为非类型模板参数类型 template<const C& cc> void A() { cout << cc.l << endl; } int main() { A<c_val1>(); A<c_val2>(); }
注意事项
- 所有非类型模板参数的实参都必须是编译期可确定的常量,无论参数是int还是自定义类类型,都不能传入运行期才会初始化的局部变量
- C++20按值传递类类型参数时,传入的临时对象要求是编译期可构造的constexpr值,类不能包含运行期才会执行的构造逻辑
内容的提问来源于stack exchange,提问作者Wulgryn
相关产品推荐
相关产品推荐

