非类型模板参数是编译期确定的常量,如int、size_t、指针等字面量或constexpr表达式;c++20起支持浮点数和类类型(有限制);必须是编译期可求值表达式,不可用运行时变量。

非类型模板参数就是模板里的“编译期常量”
它不是类型,也不是变量,而是在编译时就确定值的字面量或 constexpr 表达式——比如 int、size_t、指针、引用,甚至 C++20 起的浮点数和类类型(有严格限制)。你传进去的整数,会被当作模板签名的一部分,参与实例化。
常见错误现象:error: 'n' is not a constant expression —— 用运行时变量(如函数参数、std::cin >> 读入的值)当非类型参数;或者用了未声明为 constexpr 的变量。
- 必须是字面量(如
42)、constexpr变量、或能被编译器在编译期求值的表达式(如2 + 3) - 不能是普通局部变量、全局非常量变量、或任何含运行时逻辑的表达式
- C++17 前不支持浮点数;C++20 才允许
double等浮点字面量作为非类型参数
怎么写一个接受整数的模板(C++17 及以后最常用写法)
直接在模板参数列表里写类型和名字,像函数参数一样,但前面不加 typename 或 class:
template<int N>
struct FixedArray {
int data[N];
};
使用时: FixedArray arr; —— 这会生成一个独立的类型,和 FixedArray 完全无关。注意 N 是类型参数的一部分,不是对象成员。
立即学习“C++免费学习笔记(深入)”;
家电公司网站源码是一个以米拓为核心进行开发的家电商城网站模板,程序采用metinfo5.3.9 UTF8进行编码,软件包含完整栏目与数据。安装方法:解压上传到空间,访问域名进行安装,安装好后,到后台-安全与效率-数据备份还原,恢复好数据后到设置-基本信息和外观-电脑把网站名称什么的改为自己的即可。默认后台账号:admin 密码:132456注意:如本地测试中127.0.0.1无法正常使用,请换成l
-
N必须是编译期常量;const int N = 16;不行,必须是constexpr int N = 16;才能用于FixedArray<n></n> - 推荐用
size_t替代int表示大小(如数组长度),避免符号问题和平台差异 - 如果需要多个整数,可以连续写:
template<size_t n size_t m> struct Matrix { ... };</size_t>
为什么不能传普通变量?编译期 vs 运行期的根本区别
模板实例化发生在编译期,而普通变量的值只有到运行时才确定。编译器没法为“还没出现的值”生成代码。
典型翻车场景:int n = 5; FixedArray<n> x;</n> → 直接报错,因为 n 是运行时左值,不是常量表达式。
- 想从用户输入决定大小?不行——得换方案:用
std::vector或动态分配 - 想根据配置生成不同尺寸的缓冲区?可以:把配置项定义为
constexpr(如头文件中constexpr size_t BUF_SIZE = 256;),再传给模板 - 宏(
#define)虽然也能传整数,但没类型检查、不参与 SFINAE,非类型模板参数更安全、更现代
C++20 起支持的进阶用法和坑点
现在可以用 auto 声明非类型模板参数,让编译器自动推导类型,写起来更灵活:
template<auto N>
struct ValueWrapper { static constexpr auto value = N; };
这样 ValueWrapper、ValueWrapper、ValueWrapper<true></true> 都合法(前提是 C++20 启用)。
- 但要注意:
auto推导出的类型必须满足非类型参数要求(例如std::string仍不行,哪怕它是 constexpr) - 类类型作为非类型参数需满足“字面量类类型”条件:有 constexpr 构造函数、所有成员 public、无虚函数等,实际极少用
- 跨编译单元使用时,确保该 constexpr 值有外部链接(如定义在 .cpp 中而非仅头文件内 inline 定义),否则可能 ODR-violation
最易忽略的一点:非类型参数的值参与模板特化匹配,但不会自动隐式转换——FixedArray 和 FixedArray(unsigned int)是两个完全不同的特化,即使你只定义了 int 版本,5U 也会编译失败。








