模板的别名
传统方法使用关键字typedef定义类型的别名,他有一些限制,比如无法定义模板类型的别名
考虑这样一个场景:
我们需要一个固定以std::string为key的map,他可以映射到int或是另一个std::string,但为了定义这样一个模板的别名,我们不得不加一个外敷类:
加外敷类str_map让人感到繁琐......
使用C++11中出现的别名声明,我们可以直接给模板定义别名:
注:使用方法: using A = B; //A是B的同义词,是B的别名 using的使用方式类似赋值,将赋值号右边的类型赋给左边的类型
使用using的效果与使用typedef的效果一致,只是语法不同
使用using定义的别名,只要是类型名能出现的地方,别名都能出现
再来一个例子对比一下:
使用using定义模板时,只是在普通类型别名语句的基础上加上template参数列表即可,而不需要像typedef使用外敷模板。
函数模板的默认参数
在C++98/03中,类模板可以有默认模板参数,而函数模板不支持默认模板参数。
在C++11中上面的func函数是可以直接使用,
在函数模板的调用中,如果所有模板参数都有默认参数时,就可以像普通函数一样进行调用。
而在类模板中,哪怕所有模板参数都有默认参数,在使用时也必须在模板名后跟随"<>"来实例化
函数模板的默认模板参数不像普通函数的默认参数一样必须从右往左提供函数模板的默认模板参数。函数模板的默认模板参数也可以和自动推导结合起来使用:
需要注意的一点,显示调用函数模板时,即调用时显示指定模板参数时,参数填充顺序是从左向右的:
func<long>(123); //返回值类型为long而不是默认的int
当同时使用函数模的默认模板参数与自动推导时,会板优先自动推导,如果能按实际类型推导出类型,使用自动推导类型,反之,如果无法自动推导,则使用默认模板参数:
来自于C++11标准草案的例子:
参考:http://book.51cto.com/art/201306/400328.htm
C++ Primer
深入应用C++ 11
传统方法使用关键字typedef定义类型的别名,他有一些限制,比如无法定义模板类型的别名
考虑这样一个场景:
typedef std::map<std::string, int> map_int_t;
//........
typedef std::map<std::string, std::string> map_str_t;
//........
我们需要一个固定以std::string为key的map,他可以映射到int或是另一个std::string,但为了定义这样一个模板的别名,我们不得不加一个外敷类:
template <typename Val>
struct str_map
{
typed std::map<std::string, Val> type;
};
//....
str_map<int>::type ma;
//...
加外敷类str_map让人感到繁琐......
使用C++11中出现的别名声明,我们可以直接给模板定义别名:
template <typename Val>
using str_map = std::map<std::string, Val>;
//...
str_map<int> map1;
注:使用方法: using A = B; //A是B的同义词,是B的别名 using的使用方式类似赋值,将赋值号右边的类型赋给左边的类型
使用using的效果与使用typedef的效果一致,只是语法不同
使用using定义的别名,只要是类型名能出现的地方,别名都能出现
再来一个例子对比一下:
template <typename T>
struct fun_t
{
typedef void (*type)(T, T);
};
fun_t<int>::type xx_1;
template <typename T>
using func_t = void(*)(T, T);
func_t<int> xx_2;
使用using定义模板时,只是在普通类型别名语句的基础上加上template参数列表即可,而不需要像typedef使用外敷模板。
函数模板的默认参数
在C++98/03中,类模板可以有默认模板参数,而函数模板不支持默认模板参数。
template <typename T, typename U =int, U N = 0>
struct Foo
{
//...
};
template <typename T = int> //error
void func()
{
//...
}
在C++11中上面的func函数是可以直接使用,
在函数模板的调用中,如果所有模板参数都有默认参数时,就可以像普通函数一样进行调用。
而在类模板中,哪怕所有模板参数都有默认参数,在使用时也必须在模板名后跟随"<>"来实例化
int main()
{
Foo<> foo;
func();
return 0;
}
函数模板的默认模板参数不像普通函数的默认参数一样必须从右往左提供函数模板的默认模板参数。函数模板的默认模板参数也可以和自动推导结合起来使用:
template <typename R = int, typename U>
R func(U val)
{
val;
}
int main()
{
func(123); //返回值默认为int U自动推导为int 且默认模板参数并未从右向左提供
return 0;
}
需要注意的一点,显示调用函数模板时,即调用时显示指定模板参数时,参数填充顺序是从左向右的:
func<long>(123); //返回值类型为long而不是默认的int
当同时使用函数模的默认模板参数与自动推导时,会板优先自动推导,如果能按实际类型推导出类型,使用自动推导类型,反之,如果无法自动推导,则使用默认模板参数:
来自于C++11标准草案的例子:
template <class T, class U = double>
void f(T t = 0, U u = 0);
void g() {
f(1, 'c'); // f<int,char>(1,'c') 参数二自动推导
f(1); // f<int,double>(1,0), 使用了默认模板参数double
f(); // 错误: T无法被推导出来
f<int>(); // f<int,double>(0,0), 使用了默认模板参数double
f<int,char>(); // f<int,char>(0,0)
}
// 编译选项:g++ -std=c++11 2-11-3.cpp
参考:http://book.51cto.com/art/201306/400328.htm
C++ Primer
深入应用C++ 11