前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >c++11类型推导

c++11类型推导

原创
作者头像
江上摆渡翁
发布2020-07-09 10:56:27
5290
发布2020-07-09 10:56:27
举报
文章被收录于专栏:c++11

参考

effective modern c++

https://medium.com/@tjsw/%E6%BD%AE-c-11-universal-reference-rvalue-reference-move-semantics-1ea29f8cabdc

C++11 新特性:decltype

模板类型推导

函数模板可以看成是这样:

代码语言:txt
复制
template<typename T>
代码语言:txt
复制
void f(ParamType param);
代码语言:txt
复制
ParamType param = expr

分三种情况:

  • ParamType是一个指针或者引用(非通用universal reference引用)
  • ParamType是一个通用引用(universal reference)
  • ParamType既不是指针也不是引用

三种情况的推导规则:(推导规则推导的是T的类型)

1 ParamType是一个指针或者引用(非通用universal reference引用)

  • 如果expr的类型是引用,忽略引用的部分
  • 根据expr和ParamType对比来判断T的类型

2 ParamType是一个通用引用(universal reference)

  • 如果expr是个左值,T和ParamType都会被推导成左值引用
  • 如果expr是个右值,参考情况1

3 ParamType既不是指针也不是引用

  • 如果expr的类型是引用,忽略引用的部分
  • expr是cv的,也要忽略cv类型

实际测试:

case 1

代码语言:txt
复制
template<typename T>
void f(T& param); // param是一个引用类型

int x = 27;
const int cx = x;
const int& rx = x;

f(x);   //T: int             param: int &
f(cx);  //T: const int       param: const int &
f(rx);  //T: const int       param: const int &

case 2

代码语言:txt
复制
template<typename T>
void f(T&& param);

int x = 27;
const int cx = x;
const int& rx = x;

f(x);       //T: int &          param: int &
f(cx);      //T: const int &    param: const int &
f(rx);      //T: const int &    param: const int &
f(27);      //T: int&&          param: int &&

引用折叠(Reference collapsing)

代码语言:txt
复制
A&&       --> A&
代码语言:txt
复制
A&&&       --> A&
代码语言:txt
复制
A&&&       --> A&
代码语言:txt
复制
A&& &&      --> A&&

case2的param经过了引用折叠:

代码语言:txt
复制
int & &&            -->     int &
代码语言:txt
复制
const int & &&      -->     const int &
代码语言:txt
复制
const int & &&      -->     const int &
代码语言:txt
复制
int && &&           -->     int &&

case 3

代码语言:txt
复制
template<typename T>
void f(T param);

int x = 27;
const int cx = x;
const int& rx = x;

f(x);       //T: int        param:int
f(cx);      //T: int        param:int
f(rx);      //T: int        param:int

数组参数

数组会退化为指针:

代码语言:txt
复制
const char name[] = "J. P. Briggs"; // name的类型是const char[13] 
const char * ptrToName = name;      //数组退化成指针

template<typename T>
void f(T param);
f(name);        //T: const char*

数组的引用会保留为数组形式:

代码语言:txt
复制
const char name[] = "J. P. Briggs"; // name的类型是const char[13] 
template<typename T>
void f(T &param);
f(name);        //T: const char[13]  param: const char (&)[13]

函数参数

函数类型退化成函数指针:

代码语言:txt
复制
void someFunc(int, double);    //void (int, double)

template<typename T>
void f1(T param);

f1(someFunc);       //T: void (*)(int, double)

函数引用会保留为函数形式:

代码语言:txt
复制
void someFunc(int, double);    //void (int, double)

template<typename T>
void f2(T& param);

f2(someFunc);       //T: void (&)(int, double)

auto类型推导

auto类型推导和模板类型推导基本一致,auto相当于T,只有一个例外:{}

代码语言:txt
复制
auto x1 = 27;       //auto: int 
auto x2(27);        //auto: int
auto x3 = {27};     //auto: std::initializer_list<int>
auto x4{ 27 };      //auto: std::initializer_list<int>

auto x5 = { 1, 2, 3.0 };    //编译失败,类型不一致

decltype

decltype可以表示变量或者表达式的类型

使用方式:

代码语言:txt
复制
decltype(expr) a;   

注意点:

对一个变量名使用 decltype 得到这个变量名的声明类型。变量名属于左值表达式,但这并不 影响 decltype 的行为。然而,对于一个比变量名更复杂的左值表达式, decltype 保证返回 的类型是左值引用

代码语言:txt
复制
int x = 0;
decltype(x) a;      //a: int
decltype((x)) a;    //a: int &

尾随返回值类型

代码语言:txt
复制
//c++11版本
//auto作为函数返回值,不能推导出c和i的类型,因为这时候c和i还没有声明
//通过--> decltype(c[i])表示函数返回值类型在函数参数后声明
template<typename Container, typename Index>
auto authAndAccess(Container& c, Index i)
-> decltype(c[i])
{
  authenticateUser();
  return c[i];
}

//c++14版本
//c++14这样是可以编译过的,但是auto进行了类型推导并不和c[i]类型一致
template<typename Container, typename Index>
auto authAndAccess(Container &c, Index i)
{
    authenticateUser();
    return c[i];
}

//c++14版本
//返回值类型和c[i]保持一致
template<typename Container, typename Index>  
decltype(auto) authAndAccess(Container &c, Index i)
{
    authenticateUser();
    return c[i];
}

//使用完美转发更好,以后总结完美转发

同步更新在blog

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 参考
  • 模板类型推导
    • case 1
      • case 2
        • 引用折叠(Reference collapsing)
          • case 3
            • 数组参数
              • 函数参数
              • auto类型推导
              • decltype
              • 尾随返回值类型
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档