在前面的“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、基础使用
看一个基本的定义:
templateT Var{};//零初始化Var
模板可以有默认的模板实参,先看一下大家广为熟悉的PI的定义:
templateconstexpr T pi = T{3.1415926535897932385};
2、对模板化常量的支持
其实就是对默认值的定义,仍然以PI为例程:
templateconstexpr T pi = T(3.1415926535897932385L); // 变量模板;需要推导T的类型
3、非类型模板参数
非类型模板参数一般是指整数类型、指针和成员指针类型以及左值引用类型、枚举类型(c++11起);另外从c++20开始支持浮点类型和一些特定的字面类型。看下面的例子:
templatestd::arrayarr{}; // N个元素的数组,零初始化(译注,使用initializer进行初始化)
template
constexpr decltype(N) dval = N; // dval的类型依赖于传入的值;C++20起支持auto
4、数据成员的简化使用
在以前的模板类成员的使用过程中,在引用类模板中的静态成员时,还是有点复杂,看一下例子:
templateclass Min
{
public:
static constexpr int min = 1;
};
//使用
auto min = Min::min
而如果使用变量模板对不同的情况进行特化:
//特化定义
templateint myMin = Min::min;
//使用
auto min = myMin;
另外一个就是从c++17起对类型后缀_v的简化,在c++17以前使用某个SFINAE中的函数时,一般会有类似std::is_const::value的用法,但在之后就会见到std::is_const_v,采用就的就是变量模板定义的方式:
namespace std
{
templateconstexpr bool is_const_v = is_const::value;
}
5、变量模板全特化和偏特化
既然是模板就会有全特化和偏特化:
//全特化
templateconstexpr std::size_t SZ = sizeof(T);
template<>constexpr std::size_t SZ= 0;
//偏特化
templateconstexpr std::size_t SZ1 = sizeof(T);
templateconstexpr std::size_t SZ1= sizeof(void*);
在c++14以前即未引入变量模板以前,参数化变量一般使用类模板的静态数据成员或者constexpr 函数模板来返回所需要的值。而有这个变量模板后,一切都变得简单了。
三、例程下面看一下具体应用的例子:
//简化的例子和非类型参数
#include#include
templatestd::arrayarr{}; // 定义数组并初始化
template
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 {
templateclass numeric_limits
{
public:
static constexpr bool is_signed = false;
};
}
//可以定义:
templateconstexpr bool isSigned = mystd::numeric_limits::is_signed;
void TestSimple()
{
bool sig = isSigned;
std::cout<< "mystd numeric_limits is:"<< sig<< std::endl;
}
int main()
{
TestArray();
TestSimple();
return 0;
}
再看一个返回值的例子:
//返回值例子
templateconstexpr T PI = T(3.1415926535897932385);
templateT VAL = T(3.1415926535897932385);
templateT circular_area(T r)
{
return PI*r*r;
}
int main()
{
VAL= 3.1415;
std::cout<< VAL<< std::endl;
std::cout<< VAL<><< std::endl;
std::cout<< PI<< std::endl;
std::cout<< PI<< std::endl;
std::cout<< circular_area(2.0)<< std::endl;
return 0;
}
对于常量和变量的表示,变量模板都可以很好实现。通过上面的例子可以清晰的看到其用法。习惯了C编程的同学,可能说用宏定义一个PI不更香么,这个就看你对语言理解的深度和广度了,也考验每个开发人员对不同的开发场景的设计应用了。
没有最好,只有最合适。理论再好,不符合实际情况反而不妙。这个就需要每个人自己去思考。
从上面的变量模板的使用可以看出,其实这和模板进一步编程风格的统一有着很大的关系。当然,在这个过程中,也将一些编程的复杂度进一步降低,特别对一些本身就是一种常量的表示进一步完善代码风格。换句话说,在统一编程风格的基础上,进一步简化一些冗余的代码表示。
总之,c++的模板编程是一个很重要的发展方向,对其不断的进行完善和发展也符合c++发展的目标和希望。
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
网页题目:跟我学c++中级篇——变量模板-创新互联
网址分享:http://lswzjz.com/article/cejpcc.html