深入解析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 {};

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

相关推荐
啊?啊?6 小时前
18 从对象内存到函数调用:C++ 虚函数表原理(继承覆盖 / 动态绑定)+ 多态实战
开发语言·c++·多态原理
bkspiderx6 小时前
C++标准库:文件流类
开发语言·c++
一拳一个呆瓜6 小时前
【MFC】对话框属性:X Pos(X位置),Y Pos(Y位置)
c++·mfc
siy23336 小时前
[c语言日记] 数组的一种死法和两种用法
c语言·开发语言·笔记·学习·链表
一拳一个呆瓜6 小时前
【MFC】对话框属性:Center(居中)
c++·mfc
njxiejing6 小时前
Python NumPy安装、导入与入门
开发语言·python·numpy
hai_qin6 小时前
十三,数据结构-树
数据结构·c++
Rhys..7 小时前
Python&Flask 使用 DBUtils 创建通用连接池
开发语言·python·mysql
土了个豆子的7 小时前
04.事件中心模块
开发语言·前端·visualstudio·单例模式·c#
@菜菜_达7 小时前
Lodash方法总结
开发语言·前端·javascript