模板类型推导

2019-05-15  本文已影响0人  advanced_slowly

理解函数模板类型推导:

一段函数模板的伪码大概是这样的:

template<typename   T>
 void f(ParamType   param);

调用这个函数会是这样:

f(expr);    //  用一些表达式来调用f

在编译的时候,编译器通过expr来进行推导出两个类型:一个是T的,另一个是ParamType。通常来说这些类型是不同的,因为 ParamType通常包含一些类型的装饰,比 如const或引用特性。注意T的类型不仅和expr的类型独立,而且和Param的形式独立。
下面是三个例子:
1.Param是一个指针(包括指向const的指针)或者一个引用(包括const引用)(但并不是一个通用引用或则说万能引用)

2.Param是一个通用引用
附universal reference:如果一个函数的template parameter有着T&&的格式,且有一个deduce type T.或者一个对 象被生命为auto&&,那么这个parameter或者object就是一个universal reference.

3.Param既不是指针,也不是引用

在第一种情况和第二种情况下,T和param类型推到中,调用函数的实参的const特性将给予保留。
1.第一种情况:

当Param是一个指针或者非通用的引用:在这种情况下类型推导的过程如下
-1. 如果 expr 的类型是个引用,忽略引用的部分。
-2. 然后利用 expr 的类型和 ParamType 对比去判断 T 的类型。

# include <iostream>

template <typename T>
void f(T& param)
{
    //param = 270;      //作为测试,这里假设param的数据类型支持赋值
    std::cout << param << std::endl;
}
int main()
{
    int x = 27;         //x是一个int
    const int y = x;    //y是一个const int
    const int& z = y;   //z是一个const int的引用

    //f(x);             //T是int,Param是int &
    //f(y);             //T是const int,Param是const int &
    f(z);               //T是const int,Param是const int &

    return 0;
}

2.第二种情况:

当Param是一个通用引用:如果expr是一个左值,那么T和Param都将被推导为左值引用。如果是右值,那么就遵循普通法则

# include <iostream>

template <typename T>
void f(T&& param)
{
    std::cout << param << std::endl;
}
int main()
{

    int x = 27;         //x是一个int
    const int y = x;    //y是一个const int
    const int& z = y;   //z是一个const int的引用

    f(x);               //T是一个int &,param是一个int &
    f(y);               //T是一个const int &,param是一个const int &
    f(z);               //T是一个const int &,param是一个const int &
    f(100);             //T是一个int,Param是一个int &&

    return 0;
}

3.第三种情况:

当Param既不是指针也不是一个引用:在这种情况下由于param既不是一个指针也不是一个引用,调用函数传递给形参param的是一个实参的副本。因此调用函数的实参的const特性将不被保留。其推导法则为:

-1.和之前一样,如果expr的类型是个引用,将会忽略引用的部分。
-2.如果在忽略 expr 的引用特性,expr是个const的,也要忽略掉 const。如果 是volatile,照样也要忽略掉(volatile对象并不常见)。

# include <iostream>

template <typename T>
void f(T param)
{
    param = 270;
    std::cout << param << std::endl;
}

int main()
{
    int x = 27;         //x是一个int
    const int y = x;    //y是一个const int
    const int& z = y;   //z是一个const int的引用

    f(x);               //T是一个int,Param是一个int 
    f(y);               //T是一个int,Param是一个int
    f(z);               //T是一个int,Param是一个int
    return 0;
}

理解auto模板类型推导

除了一个例外,auto模板类型推导就是函数模板类型推导。当一个变量被声明为auto,auto相当于模板中的T,而对变量做的相关的类型限定就像ParamType。这个例外是当使用c++11的语法使用花括号来初始化auto变量时:

auto a = {100};//此时a的类型被推导为std::intializer_list<int>
上一篇下一篇

猜你喜欢

热点阅读