C++11之模板改进
改进模板的右尖括号
#include <iostream>
using namespace std;
template<typename T>
class Foo
{
public:
Foo() { cout << "create Foo..." << endl; }
~Foo() { cout << "destroy Foo..." << endl; }
private:
T _foo;
};
template<typename U>
class A
{
public:
A() { cout << "create A..." << endl; }
~A() { cout << "destroy A..." << endl; }
private:
U _a;
};
int main()
{
A<Foo<int>> a; // 在C++98/03中会报错,需要写为:A<Foo<int> > a;
std::cout << "Hello World!\n";
}
如上示例:
1、在C++98/03标准中,嵌套模板的右尖括号中间必须加空格(不加会与右移>>操作符产生二义性);
2、在C++11标准中则对此进行了优化,无需在嵌套模板的右尖括号中间加空格。
template <typename N>
struct Foo
{
N n;
};
int main(void)
{
Foo<100 >> 2> xx;
return 0;
}
如上示例:
1、在C++98/03标准中对于Foo<100 >> 2> 会正常编译;
2、在C++11标准中则报错,解决方法:Foo<(100 >> 2)>.
别名
对于别名的定义
1、在C++98/03标准中可以使用typedef;
2、在C++11标准中新增了using方式。
typedef unsigned int uint_t;
//<=>
using uint_t = unsigned int;
别名不是新的类型,不能构成函数重载
void func(unsigned int);
void func(uint_t); // error C2084: 函数“void func(unsigned int)”已有主体
引入using的意义
typedef map<string, int> map_int_t;
typedef map<string, string> map_str_t;
如上示例中,map的key都是string类型,要求将其第二个参数模板化:
//在c++98/03标准中可使用外敷模板方式实现
template<typename T>
struct map_str
{
typedef map<string, T> type;
};
//在C++11标准中则直接使用using实现
template<typename T>
using map_str = map<string, T>;
如上示例,可见using定义模板比外敷模板更简易易读。
1、typedef 无法重定义一个模板;
2、C++11引入using来重定义一个模板;
3、using包含了typedef的所有别名定义;
4、using 语法和 typedef 一样,并不会创造新的类型。
函数模板的默认模板参数
在 C++98/03 中,类模板可以有默认的模板参数,但函数模板不行;
在 C++11中,函数模板支持默认模板参数,当自动推导生效时,默认模板参数会被直接忽略。
#include <typeinfo>
template<typename T = double, typename U>
T func(U u)
{
cout << "U:" << typeid(u).name() << endl;
return u;
}
int main()
{
auto a = func(123);//U->int
cout << "a:" << typeid(a).name() << endl; // double
auto b = func<int>(123);//U->int
cout << "b:" << typeid(b).name() << endl; // int
}