深入解析C++非类型模板参数

目录

一、模板参数分类

二、非类型模板参数的应用

三、使用示例

四、非类型模板参数的限制

五、实际应用示例

六、非类型模板参数的默认值

1、基本语法

2、实际示例

[1. 静态数组类设置默认大小](#1. 静态数组类设置默认大小)

[2. 使用示例](#2. 使用示例)

3、注意事项


一、模板参数分类

模板参数可分为两种主要类型:

  1. 类型形参出现在模板参数列表中,跟在classtypename关键字之后的参数类型名称

  2. 非类型形参使用一个常量作为类或函数模板的参数,在模板中可将该参数当作常量使用


二、非类型模板参数的应用

非类型模板参数常用于需要编译期确定值的场景,例如实现静态数组类:

cpp 复制代码
template<class T, size_t N> // N是非类型模板参数
class StaticArray {
public:
    size_t arraysize() const {
        return N;
    }
    
    T& operator[](size_t index) {
        return _array[index];
    }
    
    const T& operator[](size_t index) const {
        return _array[index];
    }
    
private:
    T _array[N]; // 利用非类型模板参数指定静态数组的大小
};

三、使用示例

cpp 复制代码
int main() {
    StaticArray<int, 10> a1;    // 定义大小为10的整型静态数组
    cout << a1.arraysize() << endl; // 输出: 10
    
    StaticArray<double, 100> a2; // 定义大小为100的双精度静态数组
    cout << a2.arraysize() << endl; // 输出: 100
    
    return 0;
}

四、非类型模板参数的限制

  1. 允许的类型

    • 只允许使用整型家族(包括整数、字符、布尔等)

    • 指针和引用在特定情况下也允许

  2. 不允许的类型:浮点数、类对象、字符串字面量

  3. 编译期要求

    • 非类型模板参数必须在编译期就能确定结果

    • 因为编译器需要在编译阶段根据这些参数生成对应的类或函数


五、实际应用示例

标准库中的std::array就是一个使用非类型模板参数的典型例子:

cpp 复制代码
namespace bite {
    // 定义一个模板类型的静态数组
    template<class T, size_t N = 10> // 默认大小为10
    class array {
    public:
        T& operator[](size_t index) { return _array[index]; }
        const T& operator[](size_t index) const { return _array[index]; }
        
        size_t size() const { return N; } // 直接返回模板参数N
        bool empty() const { return N == 0; }
        
    private:
        T _array[N];
    };
}

非类型模板参数为C++模板编程提供了更多灵活性,特别是在需要编译期常量的场景中非常有用。


六、非类型模板参数的默认值

非类型模板参数可以设置默认值,这与类型模板参数设置默认值的语法规则相同。

1、基本语法

cpp 复制代码
template <class T, size_t N = 默认值>  // 为非类型参数N设置默认值
class ClassName {
    // 类定义
};

2、实际示例

1. 静态数组类设置默认大小

cpp 复制代码
template <class T, size_t N = 10>  // 默认数组大小为10
class StaticArray {
public:
    size_t size() const { return N; }
    // ... 其他成员函数
private:
    T _array[N];
};

2. 使用示例

cpp 复制代码
int main() {
    StaticArray<int> a1;      // 使用默认大小10
    StaticArray<double, 20> a2; // 显式指定大小20
    
    cout << a1.size() << endl; // 输出: 10
    cout << a2.size() << endl; // 输出: 20
    
    return 0;
}

3、注意事项

  1. 默认参数规则

    • 与函数默认参数类似,从右向左设置默认值

    • 如果某个模板参数有默认值,它右边的所有参数都必须有默认值

  2. 正确示例

    cpp 复制代码
    template <class T = int, size_t N = 10>  // 正确
    class A {};
  3. 错误示例

    cpp 复制代码
    template <class T = int, size_t N>  // 错误:N没有默认值
    class B {};

这种技术广泛用于需要编译期确定大小的容器类,是模板元编程中的重要技术之一。

相关推荐
代码游侠1 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
devmoon2 小时前
运行时(Runtime)是什么?为什么 Polkadot 的 Runtime 可以被“像搭积木一样”定制
开发语言·区块链·智能合约·polkadot·runtmie
时艰.2 小时前
Java 并发编程 — 并发容器 + CPU 缓存 + Disruptor
java·开发语言·缓存
忆~遂愿2 小时前
GE 引擎进阶:依赖图的原子性管理与异构算子协作调度
java·开发语言·人工智能
沐知全栈开发2 小时前
API 类别 - 交互
开发语言
MZ_ZXD0012 小时前
springboot旅游信息管理系统-计算机毕业设计源码21675
java·c++·vue.js·spring boot·python·django·php
人道领域2 小时前
SSM框架从入门到入土(AOP面向切面编程)
java·开发语言
铅笔侠_小龙虾2 小时前
Flutter 实战: 计算器
开发语言·javascript·flutter
2的n次方_3 小时前
Runtime 执行提交机制:NPU 硬件队列的管理与任务原子化下发
c语言·开发语言
2501_944711433 小时前
JS 对象遍历全解析
开发语言·前端·javascript