C++模板参数推导

为了实例化函数模板,必须知道每个模板参数,但不是必须指定每个模板参数。如果可能,编译器将从函数参数中推断出缺少的模板参数。当尝试调用函数、获取函数模板的地址,以及在其他一些上下文中时,会发生这种情况:

类型转换

template<typename ToType, typename FromType> ToType convert(FromType f);
 
void g(double d) 
{
   
    int i = convert<int>(d);    // calls convert<int, double>(double)
    char c = convert<char>(d);  // calls convert<char, double>(double)
    int(*ptr)(float) = convert; // instantiates convert<int, float>(float) 
                                // and stores its address in ptr
}

参数包(Parameter pack)

模板参数包

模板参数包是接受零个或多个模板参数(非类型、类型或模板)的模板参数。

函数参数包

函数参数包是接受零个或多个函数参数的函数参数。
具有至少一个参数包的模板称为可变参数模板。

从函数调用中推导参数类型

模板实参推导尝试确定模板实参(类型模板参数 Ti 的类型、模板模板参数 TTi 的模板和非类型模板参数 Ii 的值),可以将其代入每个参数 P 以生成推导出的类型 A,其中与参数 A 的类型相同,经过以下列出的调整。

多个参数

如果有多个参数,则分别推导每个 P/A 对,然后,将推导的模板参数组合起来。如果任何 P/A 对的推导失败或不明确,或者不同的对产生不同的推导模板参数,或者任何模板参数既没有推导也没有明确指定,则编译失败。

如果从 P 中删除引用和 cv 限定符给出 std::initializer_list<P’>,并且 A 是一个花括号初始化列表,则对初始化列表的每个元素执行推导,以 P’ 作为参数和列表元素A’ 作为论据:

从函数调用中推导参数类型

template<class T> void f(std::initializer_list<T>);
f({
   1, 2, 3});  // P = std::initializer_list<T>, A = {1, 2, 3}
               // P'1 = T, A'1 = 1: deduced T = int
               // P'2 = T, A'2 = 2: deduced T = int
               // P'3 = T, A'3 = 3: deduced T = int
               // OK: deduced T = int
f({
   1, "abc"}); // P = std::initializer_list<T>, A = {1, "abc"}
               // P'1 = T, A'1 = 1: deduced T = int
               // P'2 = T, A'2 = "abc": deduced T = const char*
               // error: deduction fails, T is ambiguous

推导P’[N]

如果从 P 中删除引用和 cv 限定符,得到 P’[N],并且 A 是非空的大括号初始化列表,则按上述执行推导。除非 N 是非类型模板参数,否则推导从初始化列表的长度:

如何得到 P'[N]的例子

template<class T, int N> void h(T const(&)[N]);
h({
   1, 2, 3}); // deduced T = int, deduced N = 3
 
template<class T> void j(T const(&)[3]);
j({
   42}); // deduced T = int, array bound is not a parameter, not considered
 
struct Aggr {
    int i; int j; };
template<int N> void k(Aggr const(&)[N]);
k({
   1, 2, 3});       // error: deduction fails, no conversion from int to Aggr
k({
   {
   1}, {
   2}, {
   3}}); // OK: deduced N = 3
 
template<int M, int N> void m(int const(&)[M][
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值