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

目录

一、模板参数分类

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

三、使用示例

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

五、实际应用示例

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

1、基本语法

2、实际示例

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

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

3、注意事项


一、模板参数分类

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

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

  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 {};

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

相关推荐
andyweike16 小时前
php笔记
开发语言·笔记·php
蒸蒸yyyyzwd16 小时前
秋招学习笔记 day46
c++·八股
Circ.16 小时前
Python 调试 Litellm 本地大模型接口:模型列表与对话接口实操踩坑记录
开发语言·python
现任明教教主~18 小时前
Thinkphp站群蜘蛛池SaaS系统YanyvSEO含多用户/积分/六大引擎计费/易支付对接
java·开发语言·spring
Zhou14113618 小时前
SpringSecurity_02_授权与高级功能
开发语言·python
码匠许师傅19 小时前
【C++三方组件】cpp-httplib:一个头文件起 HTTP 服务
开发语言·c++·http
无名猿20 小时前
new/delete 与 malloc/free:为什么绝对不能混用
c++·内存管理·现代c++·踩坑记录
小小小小钰儿20 小时前
1.5-Python网络编程
开发语言·网络·python·web安全·计算机·网络安全