模板别名
在C++98/03里,我们可以通过typedef 关键字定义一个类型的别名,比如 typedef unsigned int uint_t;在这里我们定义了unsigned int类型的别名和uint_t,在以后需要使用unsigned int的时候我们都可以用uint_t替换,但是uint_t仅仅是作为unsigned int的一个别名,如下的定义是不合法的:
-
typedef unsigned int uint_t;
-
void func(unsigned int);
-
void func(uint_t);
考虑下面例子,我们在实际编程中经常使用到STL中的MAP,我们MAP的string类型的数据作为MAP的key,我们想根据STRING类型的KEY映射为一个String,int,long等类型的数据.
-
typedef std:: map< std:: string, int> map_t;
-
//...
-
typedef std:: map < std:: string, std:: string > map_str;
-
//...
-
template < typename T>
-
typedef std:: map< std:: string, T> map;
-
map< int> map_i;
-
map< std:: string> map_str;
-
template < typename T>
-
struct alias_map
-
{
-
typedef std:: map< std:: string, T> map;
-
};
-
-
alias_map< int>:: map map_t;
-
alias_map< int>:: map map_str;
通过包裹类的方法虽然可以实现上述的需求,但是一看代码就觉得,这个代码可读性差,不就是定义一个变量吗?还需要整一个包裹类来封装下,增加代码里不说,看着都烦,小幸运的是C++11终于让你可以不用通过上述这种臃肿的方式来实现这个需求了。C++11中,新增了一个特性就是可以通过使用using来为一个模板定义别名,比如说上述的需求,使用C++11就可以这样实现:
-
template < typename T>
-
using alias_map = std:: map < std:: string, T > ;
-
alias_map< int> map_t;
-
alias_map< std:: string> map_str;
-
typedef unsigned int uint_t;
-
using uint_t = unsigned int;
-
-
typedef std:: map< std:: string, int> map_t;
-
using map_t = std:: map < std:: string, int > ;
-
typedef void(*func)(int, int);
// 相当于给func定义了一个类型,此时不能省略
-
using func = void(*)( int, int);
// 相当于给func定义了一个类型,此时后面的void(*fun)(int, int)中的fun不能填写。
-
template< typename T>
-
struct FuncSt
-
{
-
typedef void(*func)(T, T);
-
};
-
-
FuncSt< int>::func func_typedef;
-
-
-
template< typename T>
-
using func_using = void(*)(T, T);
-
func_using< int> func_using;
函数的默认模板参数
在C++98/03里,类模板是支持默认的模板参数的,比如:
-
template< class T, class U = int, U n= 0>
-
struct Foo
-
{
-
//
-
};
-
template < typename T = int> //error in C++98/03 default template arguments
-
void func( void)
-
{
-
//...
-
}
C++11中函数的默认模板参数在使用规则上和其他的默认参数也有一些区别,普通函数的默认参数必须写在参数列表的最后,而函数模板的参数就没有这个限制,因此当使用默认模板参数和模板参数自动推导时就显示十分灵活,可以指定函数中的一部分参数是默认参数,另一部分采用自动推导。比如:
-
template < typename R = int, typename U>
-
R func(U val)
-
{
-
//...
-
}
-
-
int _tmain( int argc, _TCHAR* argv[])
-
{
-
func( 123);
-
return 0;
-
}
func<long>(123); //func返回类型是填充类型long
这个细节虽然简单,但是在多个默认模板参数和多个模板参数自动推导穿插使用时会容易被忽略掉,造成使用上的一些意外,建议在使用的时候尽量还是价格默认模板参数写在模板参数的末尾;另外当默认模板参数和自动参数推导同时使用时,若函数模板无法推导出参数类型时,编译器将使用默认模板参数,否则将使用自动推导的参数类型。这个跟函数的默认参数使用规则是一致的,比较好理解。