1.1 模板别名
使用场景:
这里使用新的using别名语法定义了std::map的模板别名map_str_t。比起之前的使用外敷结构体加上typedef构建的map_str,它完全就像是一个新的map类模板,代码书写上简洁了很多。
typedef std::map<std::string, int> map_int_t;
typedef std::map<std::string, std::string> map_str_t;
上面的形式在C++98/03中,是不能实现直接。如果要定义如下的模板别名的时候,需要这样写:
template<typename T> struct map_str;
{
typedef std::map<std::string, T> type;
};
map_str<int>::type kk;
从上面可以看出如果要定义上面说的map_str_t别名,就需要外敷一个结构体来实现,这样的实现未免比较麻烦。现在在C++11中已经可以使用重定义一个模板的语法了,如下:
template<typename T> using map_str_t = std::map<std::string, T>;
map_str_t mm;
这里使用新的using别名语法定义了std::map的模板别名map_str_t。比起之前的使用外敷结构体加上typedef构建的map_str,它完全就像是一个新的map类模板,代码书写上简洁了很多。
1.2 using/typedef比较
而实际上using别名语法覆盖了typedef的全部功能。下面是两种语法的比较:
typedef的定义方法和变量的声明类似:像声明一个变量一样,声明一个重定义类型,之后在声明之前加上typedef即可。这种写法凸显了C/C++中的语法一致性,但有时增加了代码的阅读难度,如定义函数指针的时候:
与之相比using的表达式就简明了很多
//重定义unsigned int
typedef unsigned int uint_t;
using uint_t = unsigned int;
//重定义std::map
typedef std::map<std::string, int> map_str_t;
using map_str_t = std::map<std::string, int>;
从上面可以看出,在重定义普通类型上面,两种使用方法的效果是等价的,唯一的不同是定义的语法。typedef的定义方法和变量的声明类似:像声明一个变量一样,声明一个重定义类型,之后在声明之前加上typedef即可。这种写法凸显了C/C++中的语法一致性,但有时增加了代码的阅读难度,如定义函数指针的时候:
typedef void (*func)(int, int);
与之相比using的表达式就简明了很多
using func = void (*)(int, int);
1.3 函数模板的默认模板参数
C++98/03中可以为类模板指定默认模板参数
template<typename T, typename U, T U=0> class A{};
但是对于函数模板的的默认模板参数是不能指定的,或报错。
template<typename T = int> func2(T a){}
上面的在模板函数中的限制在C++11中已经被解除了,上面的func2函数可以直接在C++11中使用。此外函数模板默认模板参数在使用规则上和其他的默认参数也有些不同,因为他没有必须放置在参数表末尾的限制。在调用函数模板时,若显示指定模板的参数,由于参数填充顺序是从参数表的右边开始到左边的。另外,当默认模板参数和模板参数自动推导同时使用时,若函数模板无法自动推导出参数类型,则编译器将使用默认模板参数;否则将使用自动推导出的参数类型。