You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++模板如何支持非静态非类型参数?C++20实例化疑问解析

C++20非类型模板参数常见问题解答

为什么C++20允许用非静态对象实例化模板?

C模板确实是编译期构造的,但C20对**非类型模板参数(NTTP)**的规则做了大幅扩展,打破了之前只能用静态存储期常量的限制。

在C20之前,非类型模板参数只能是基本类型、指向静态对象的指针/引用、枚举这类简单类型。但C20引入了**结构类型(structural type)**作为NTTP的合法类型——简单说,只要一个类型是聚合类型、没有用户定义的构造/析构/赋值函数、没有虚函数,且所有成员都是结构类型或基本类型,它就是结构类型(比如示例里的struct X {}就完全符合)。

对于结构类型的NTTP,C++20允许传递自动存储期(也就是非静态)的对象,前提是这个对象的初始化表达式是常量表达式,而且它的所有成员值在编译期是可确定的。编译器会在编译期把这个对象的逐成员值拷贝下来,作为模板实例的一部分——本质上还是编译期完成构造,只是允许用自动存储期的对象来提供编译期已知的值而已。

如何设置非静态非类型模板参数?

结合你的代码示例,分三步来做:

  1. 定义符合要求的参数类型
    你的自定义类型必须是C++20认可的结构类型。比如示例里的struct X {}:它是聚合类型,没有自定义的特殊成员函数,也没有虚函数,完全满足结构类型的要求。如果你的类型有自定义构造函数或者虚函数,就没法用来做非类型模板参数。

  2. 声明模板时指定非类型参数
    在模板参数列表里直接声明类型和参数名就行,像示例里这样:

    template<typename T, X x> auto f() {
        return x;
    }
    

    这里的X x就是一个非类型模板参数,类型是我们自定义的结构类型X。

  3. 实例化时传递非静态对象
    只要传递的非静态对象是用常量表达式初始化的,就能作为模板实参。比如示例里的main函数:

    int main() {
        auto x = X{}; // X{}是常量表达式,x的所有值编译期都能确定
        f<double, x>(); // 合法,编译器会把x的编译期值传入模板实例
    }
    

    注意:如果你的对象是用运行时才能确定的值初始化的(比如X x{some_runtime_variable}),那肯定不能作为NTTP,毕竟模板实例化必须在编译期完成。


内容的提问来源于stack exchange,提问作者cmutex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 15:39:21