当前位置: 首页 > news >正文

非类型模板参数详解

概念介绍

非类型模板参数(Non-type template parameters),顾名思义在模板中这个参数不是表示一个类型,而是表示一个值,它必须是编译时常量。

基本语法如下所示:

// 基本形式
template <type-name parameter-name>
template <typename T, int N>  // N 是非类型模板参数

如上所示,T作为模板参数表示一个类型,而N作为一个模板参数,表示的并不是一个类型,而是一个数值。

template<T, int N>
class array{
    private:
        int buffer[N];
    ....
}

从上面的例子可以看到非类型模板参数N作为一个数值,供模板参数使用。

非类型模板参数在c++98就已经引入了,只是我们平时的使用中可能对模板参数是一个类型这种形似见的比较多,所以对非类型模板参数有所忽略。

非类型模板参数随着版本的演进

随着版本的变化,非类型模板参数的特性不断丰富,总体来说就是早期版本非类型模板参数仅支持部分基本的数据类型,而随着版本的不断发展,支持的数据类型越来越多,甚至到了c++20版本已经支持将自定义的类类型作为非类型模板参数传入。

c++98版本

在早期版本仅支持整型、枚举类型、指针、引用、成员函数指针作为非类型模板参数。

//基本数据类型
template<int N>
struct array{
    int data[N];
}

//指针和引用
template<int* p>
struct pointer
{
    //使用P
}

//枚举类型
enum Color{RED, GREEN, BLACK};
template<Color C>
struct ColorHolder{
    //内部使用C
}

c++11版本

引入了nullptr和constexpr的支持

template <int* P = nullptr>
struct Pointer {};

constexpr int getValue() { return 42; }
template <int N = getValue()>
struct Value {};

c++14变量模板支持

template <int N>
constexpr int value = N;

static_assert(value<42> == 42);

可以看到支持对一个变量设置模板参数。

c++17版本带来的变化

c++17相对于之前的版本引入了一个很重要的改进,即在定义模板时,对于非类型模板参数来说无需使用显式的类型来声明非类型模板参数,而是可以使用auto关键即可。请看下面的例子:

// 自动推导类型
template <auto N>
struct Value {
    using type = decltype(N);
    static constexpr auto value = N;
};

Value<42> v1;    // int
Value<'c'> v2;   // char
Value<true> v3;  // bool

请看上面的例子,在c++17之前在声明时不能使用auto关键字,而是必须显式的将非类型模板参数的类型声明出来,下面在看一个更具体的例子:

//c++17之前
// 使用auto作为非类型模板参数
template <int N>
class Array {
    int data[N];  // N的类型会被自动推导
};

Array<42> arr1;    // N 被推导为 int
Array<'c'> arr2;   // 错误,与声明不一致


//c++17之后
// 使用auto作为非类型模板参数
template <auto N>
class Array {
    int data[N];  // N的类型会被自动推导
};

Array<42> arr1;    // N 被推导为 int
Array<'c'> arr2;   // N 被推导为 char

c++20版本

这个版本对于非类型模板参数也是一个重大的改进,在该本支持了将类类型和浮点类型。在这之前非类型模板参数是不支持类类型和浮点数类型的。请看下面的例子:

class Point
{
    private:
        int x;
        int y;
}
//c++20之前
template<Point p>  //错误,不支持类类型,浮点数同理
struct PointTemplate 
{
    static constexpr Point value = p;
}

//c++20之后
template <Point p>
struct PointTemplate {
    static constexpr Point value = p;
};

static constexpr Point origin{0, 0};
PointTemplate<origin> pt;

注意事项

无论版本如何演进,非类型模板参数,都必须是在编译时确定非类型模板参数的数值的,不能在运行时通过变量的方式确定非类型模板参数的值。请看下面的例子:

template<int N>
struct Array
{
    int buffer[N];
}

int var = 10;
Array<var> a1;  //编译错误,必须在编译时确定该值
Array<10> a2;  //编译正确,在编译时非类型模板参数的数值已经确定

constexpr int var1 = 20;
Array<var1> a3;   //编译正确,因为constexpr修饰的变量就是在编译阶段生效的。

相关文章:

  • react tailwindcss最简单的开始
  • KNN算法深度解析:从决策边界可视化到鸢尾花分类实战
  • bat与powershell语法教程以及容易遇到的坑
  • go语言gRPC使用流程
  • AI数据分析的优势分析
  • 浙江大学DeepSeek系列专题线上公开课第二季第五期即将上线!deepseek人文艺术之美专场来啦!
  • 什么是COSMIC功能点评估方法
  • [福游宝——AI智能旅游信息查询平台]全栈AI项目-阶段二:聊天咨询业务组件开发
  • 系统性能优化总结与思考-第一部分
  • 简简单单实现一个Python+Selenium的自动化测试框架
  • LabVIEW 发电机励磁系统监测与诊断
  • CExercise_05_1伪随机数_1写一个随机发牌程序,由用户指定发几张票,然后打印用户得到的手牌。
  • 前端常考面试题目详解
  • 软件更新 | 以太网通信仿真功能已上线!TSMaster 202503 版本更新速览
  • C++中的高阶函数
  • Redis之缓存穿透
  • 【NLP】24. spaCy 教程:自然语言处理核心操作指南(进阶)
  • 《AI大模型应知应会100篇》第5篇:大模型发展简史:从BERT到ChatGPT的演进
  • InnoDB的MVCC实现原理?MVCC如何实现不同事务隔离级别?MVCC优缺点?
  • 基于LangGraph的智能报告生成平台项目分析
  • 男子拍摄女性视频后在网上配发诱导他人违法犯罪文字,已被警方行拘
  • 美国开始从叙利亚撤出数百人,分析人士担忧“伊斯兰国”威胁再起
  • 美肯塔基州长警告:关税或致美家庭年增数千美元支出
  • 智能网联汽车不得夸大宣传,专家呼吁引导企业规范宣传
  • 绿城中国5.39亿元竞得浙江台州住宅用地,刷新板块单价纪录
  • 锦州4名少年偷手机89部还发视频炫耀,店主:贼抓了又放,手机向谁要