非类型模板参数
来源:互联网 发布:mac安装flash插件 编辑:程序博客网 时间:2024/05/21 22:40
/*
模板除了定义类型参数,我们还可以在模板定义非类型参数。
什么是非类型形参?顾名思义,就是表示一个固定类型的常量而不是一个类型。
固定类型是有局限的,只有整形,指针和引用才能作为非类型形参,
而且绑定到该形参的实参必须是常量表达式,即编译期就能确认结果。
非类型形参的局限:
1.浮点数不可以作为非类型形参,包括float,double。具体原因可能是历史因素,也许未来C++会支持浮点数。
2.类不可以作为非类型形参。
3.字符串不可以作为非类型形参
4.整形,可转化为整形的类型都可以作为形参,比如int,char,long,unsigned,bool,short(enum声明的内部数据可以作为实参传递给int,但是一般不能当形参)
5.指向对象或函数的指针与引用(左值引用)可以作为形参
非类型实参的局限:
1.实参必须是编译时常量表达式,不能使用非const的局部变量,局部对象地址及动态对象
2.非Const的全局指针,全局对象,全局变量(下面可能有个特例)都不是常量表达式。
3.由于形参的已经做了限定,字符串,浮点型即使是常量表达式也不可以作为非类型实参
备注:常量表达式基本上是字面值以及const修饰的变量
*/
#include "stdafx.h"
#include<iostream >
using namespace std;
//例1-----------------------------------------------------
const int r = 777;
template< int r >
void R()
{
cout << r << endl;
}
//例2-----------------------------------------------------
char x1[] = "saaaa";;//全局变量
char * x2 = "qweqeq";;//全局变量
char * const x3 = "qweqeq";;//全局变量 指针常量
template<typename T, char* x>
void X(T t)
{
cout << t << ", " << x << endl;
};
//例3----------------------------------------------------
template<int a >
void A(const char(&p)[a] )
{
std::cout << "size : " << a << " " << p << std::endl;
}
//例4----------------------------------------------------
//引用
struct Y {};
Y y;
template<const Y& b>
struct Z {};
int q = 1;
template<const int& q>
struct Q {};
//例5----------------------------------------------------
//数组指针
int b[5] = {11,22,33,44};
template<int(&pa)[5]>
void B()
{
cout << pa[1] << endl;
};
//例6----------------------------------------------------
//函数指针
void f(int a)
{
cout << "a is "<<a << endl;
}
template<void(*pf)(int)>
void C()
{
pf(111);
};
//例7---------------------------------------------------
//模板模板参数
template<typename T> class N { public: int x; }; // primary template
template<class T> class N<T*> { public: long x; }; // partial specialization
template< template<typename> class V >
class M
{
public:
V<int> y; // uses the primary template
V<int*> z; // uses the partial specialization
};
int main()
{
//例1----------------------------------------------------
R<666>();
R<r>();
const int r2 = 888;
R<r2>();
int r3 = 999; //局部变量
// R<r3>();// 错误: 包含非静态存储持续时间的变量不能用作非类型参数
//例2----------------------------------------------------
X<int, x1>(3);
// X<int, x2>(4); // 错误: 应为编译时常量表达式
// X<int, x3>(5); // 错误: 涉及带有内部链接的对象的表达式不能用作非类型参数
char *x4 = "adsas";//局部变量,写在main函数里面
// X<int, x4>(6);// 错误: 包含非静态存储持续时间的变量不能用作非类型参数
// X<int, "sdfsd">(7);//错误: 模板参数不能封引用非外部实体
//例3----------------------------------------------------
A("hello") ;
A<6>("hello");
//例4----------------------------------------------------
Z<y> z;
Q<q> q1;
//例5----------------------------------------------------
B<b>(); // ok: no conversion
//例6----------------------------------------------------
C<&f>(); // ok: overload resolution selects f(int)
//例7----------------------------------------------------
M<N> m = M<N>(); //显示地调用内建类型的缺省构造函数
cout << m.y.x << endl;
return 0;
}
/*
//关于指针常量和常量指针可以参考博客
Const用法总结(快速区分指针常量与常量指针)
这里大家可能会有几个疑问
①.到底为什么字符串不能作为实参?
答:两个内容完全相同 的字符串字面常数可能存在两个不同的地址上。
有个方法: extern char const hello[] = "Hello World!";这里必须使用关键词 extern,因为const array 采用内部链接(internal linkage)。
②.变量b和c作为模板实参为什么错误不同?
答:首先解释b实参,b在这里看做是一个指针,是一个全局指针,但是他不是一个常量表达式,所以b不对。
我们再看看c,c相比于b对了一个const修饰符,表示这个指针是一个常量。然而const是一个比较特别的关键字,
他具有内部链接属性(关于内连接参考博客 理解C++的链接:C++内链接与外链接的意义),
也就是说仅在定义这个变量的文件内可见,不会造成不同编译单元的混编时的链接错误。
这个特性对于模板来说可是有问题的,就像问题①所描述的,由于每个编译单元可能都有一个c变量,
导致在编译时,实例化多个c,而且c的地址还不同,这就造成二个模板的实例是两个不同且不兼容的类型。
③为什么a变量作为实参可以?
答:我看过一些书籍,上面举得例子都是用const修饰不行的情况下在加extern来形成extern const chara[] = "saaa";
这样形式的语句,extern和const联合使用确实可以压制const的内部属性。
这个a这里可以看做一个数组类型(进一步理解数组与指针的关系可以参考博客
char * itoa(int, char *, int); 第二个参数明明是char*,为什么却又不能是“char*”? )
,那么我们看到他不仅避免了①中的实例化地址不同的问题(因为是全局唯一的),
而且还避免了const带来的内部链接问题,所以这一项可能是经过编译器优化过的结果。
*/
- 模板非类型参数
- 非类型模板参数
- 非类型模板参数
- 非类型模板参数
- 非类型模板参数
- 非类型模板参数
- 非类型的模板参数
- 非类型模板类参数
- 非类型函数模板参数
- 模板之非类型模板参数
- 模板笔记003 - 非类型模板参数
- C++ Templates:非类型模板参数
- 非类型模板参数知识点梳理
- 非类型模板参数知识点梳理
- STL学习之--非类型模板参数
- 为什么要使用非类型模板参数?
- 非类型模板参数的限制
- 非类型模板参数与 非类型类模板参数的使用
- Bitmap基础
- 2012蓝桥杯国赛第三题 输入汉字显示大写首字母
- 简单的form表单验证
- window.location下的属性说明
- xtrabackup备份与恢复
- 非类型模板参数
- 进程间通信系列(7)匿名管道和命名管道异同
- virtualbox 网络连接 没有host only
- IMWeb训练营作业
- 斐波那契数列,计算n = 50时数列的值;输入n,返回数列结果
- 434. Number of Segments in a String
- UILabel描边效果
- x265文献阅读:CU模式判决
- 树状数组总结