IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 跟我学c++中级篇——变量模板 -> 正文阅读

[C++知识库]跟我学c++中级篇——变量模板

一、变量模板(Variable Templates)

在前面的“C++11中对模板的支持”中,对变量模板进行过基本的描述。变量模板的用处也分析的比较简单,本篇文章专门把这个变量模板拿出来,对其进行更详细的说明。c++14以后,c++的新的标准提供了对变量模板的支持。变量模板的作用,其实仍然是对模板编程的支持,简化定义,增加对模板化常量的支持。其基本的语法形式如下:

template < parameter-list > variable-declaration		
variable-declaration -	a declaration of a variable. The declared variable name becomes a template name.
parameter-list -	a non-empty comma-separated list of the template parameters, each of which is either non-type parameter, a type parameter, a template parameter, or a parameter pack                         of any of those.

按上面的语法表示可以看出,变量模板的定义还是非常简单的,它的模板参数支持非类型形参、类型形参和模板形参。

二、作用和应用

1、基础使用
看一个基本的定义:

template<typename T> T Var{};//零初始化Var

模板可以有默认的模板实参,先看一下大家广为熟悉的PI的定义:

template<typename T = long double>
constexpr T pi = T{3.1415926535897932385};

2、对模板化常量的支持
其实就是对默认值的定义,仍然以PI为例程:

template<class T>
constexpr T pi = T(3.1415926535897932385L); // 变量模板;需要推导T的类型

3、非类型模板参数
非类型模板参数一般是指整数类型、指针和成员指针类型以及左值引用类型、枚举类型(c++11起);另外从c++20开始支持浮点类型和一些特定的字面类型。看下面的例子:

template<int N>
std::array<int, N> arr{}; // N个元素的数组,零初始化(译注,使用initializer进行初始化)

template<auto N>
constexpr decltype(N) dval = N; // dval的类型依赖于传入的值;C++20起支持auto

4、数据成员的简化使用
在以前的模板类成员的使用过程中,在引用类模板中的静态成员时,还是有点复杂,看一下例子:

template<typename T>
class Min
{
public:
    static constexpr int min = 1;
};
//使用
auto min = Min<int>::min

而如果使用变量模板对不同的情况进行特化:

//特化定义
template<typename T>
int myMin = Min<T>::min;
//使用
auto min = myMin<int>;

另外一个就是从c++17起对类型后缀_v的简化,在c++17以前使用某个SFINAE中的函数时,一般会有类似std::is_const::value的用法,但在之后就会见到std::is_const_v,采用就的就是变量模板定义的方式:

namespace std
{
    template<typename T> constexpr bool is_const_v = is_const<T>::value;
}

5、变量模板全特化和偏特化
既然是模板就会有全特化和偏特化:

//全特化
template<typename T> constexpr std::size_t SZ = sizeof(T);
template<> constexpr std::size_t SZ<void> = 0;

//偏特化
template<typename T> constexpr std::size_t SZ1 = sizeof(T);
template<typename T> constexpr std::size_t SZ1<T*> = sizeof(void*);

在c++14以前即未引入变量模板以前,参数化变量一般使用类模板的静态数据成员或者constexpr 函数模板来返回所需要的值。而有这个变量模板后,一切都变得简单了。

三、例程

下面看一下具体应用的例子:

//简化的例子和非类型参数
#include <iostream>
#include <array>

template<int N>
std::array<int, N> arr{}; // 定义数组并初始化

template<auto N>
constexpr decltype(N) dval = N;  

void TestArray()
{
    std::cout << dval<'c'> << std::endl;  

    arr<10>[0] = 42; // 设置全局arr第1个元素的值
    for (std::size_t i = 0; i < arr<10>.size(); ++i) 
    { // 使用arr中的值
        std::cout << arr<10>[i] << std::endl;
    }
}
namespace  mystd {
    template<typename T>
    class numeric_limits 
    {
    public:

        static constexpr bool is_signed = false;

    };
}
//可以定义:
template<typename T>
constexpr bool isSigned = mystd::numeric_limits<T>::is_signed;
void TestSimple() 
{
    bool sig = isSigned<char>;
    std::cout << "mystd numeric_limits is:" << sig << std::endl;
}
int main()
{
    TestArray();
    TestSimple();
   
    return 0;
}

再看一个返回值的例子:

//返回值例子
template<typename T>
constexpr T PI = T(3.1415926535897932385);

template<typename T=long double>
T VAL = T(3.1415926535897932385);

template<typename T>
T circular_area(T r)
{
    return PI<T>*r*r;
}

int main()
{
    VAL<float> = 3.1415;
    std::cout << VAL<float> << std::endl;
    std::cout << VAL<> << std::endl;
    std::cout << PI<int> << std::endl;
    std::cout << PI<double> << std::endl;
    std::cout << circular_area(2.0) << std::endl;   
    return 0;
}

对于常量和变量的表示,变量模板都可以很好实现。通过上面的例子可以清晰的看到其用法。习惯了C编程的同学,可能说用宏定义一个PI不更香么,这个就看你对语言理解的深度和广度了,也考验每个开发人员对不同的开发场景的设计应用了。
没有最好,只有最合适。理论再好,不符合实际情况反而不妙。这个就需要每个人自己去思考。

四、总结

从上面的变量模板的使用可以看出,其实这和模板进一步编程风格的统一有着很大的关系。当然,在这个过程中,也将一些编程的复杂度进一步降低,特别对一些本身就是一种常量的表示进一步完善代码风格。换句话说,在统一编程风格的基础上,进一步简化一些冗余的代码表示。
总之,c++的模板编程是一个很重要的发展方向,对其不断的进行完善和发展也符合c++发展的目标和希望。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-12-25 10:47:31  更:2022-12-25 10:49:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 7:06:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码