4

Effective Modern C++(1): 类型推导

 1 year ago
source link: https://keys961.github.io/2022/05/28/Effective-Modern-C++(1)/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1. 模板类型推导

考虑下面的模板:

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

1.1. ParamType为指针或引用

ParamTypeT&

  • 传入intT = intParamType = int&

  • 传入const intT = const intParamType = const int&

  • 传入const int&T = const intParamType = const int&

    • 推导的&被忽略

ParamTypeconst T&

  • 传入intT = intParamType = const int&

  • 传入const intT = intParamType = const int&

    • 推导的const被忽略
  • 传入const int&T = intParamType = const int&

    • 推导的const&都被忽略

对于指针(T*const T*)也是一样

1.2. ParamType为通用引用

ParamTypeT&&,可接受左值和右值:

  • 若传入参数为左值(即可取地址),TParamType会被推导为左值引用

    • 传入intT = int&(这里推导增加了引用),折叠后ParamType = int&

    • 传入const intT = const int&(这里推导增加了引用),折叠后ParamType = const int&

    • 传入const int&T = const int&,折叠后ParamType = const int&

  • 若传入参数为右值,同第1节

    • 传入int右值,如数字:T = intParamType = int&&

折叠规则:只要有左值引用,优先折叠为左值引用

  • & + & -> &

  • & + && -> &

  • && + & -> &

  • && + && -> &&

1.3. 传值

ParamTypeT

  • 若传入参数包含引用,引用被忽略,再忽略constvolatile

    • 传入int, const int, const int&TParamType都为int

    • 这说明了传入的参数就是一个拷贝,和外面的无关了

    • 若传入const char* const,拷贝了指针,但右边的const被忽略,所以变成了指针可变、内容不可变

1.4. 数组

ParamTypeT

  • 若传入int数组,则会退化为const int*指针

ParamTypeT&

  • 若传入int数组,则T会推导为int[]

当然,更推荐直接使用std::array

1.5. 函数

会被退化为函数指针

1.6. 总结

  1. ParamTypeT&,传入引用时,推导会将引用忽略

  2. ParamTypeT&&,传入左值引用,会优先推导为左值引用

  3. ParamTypeT,引用、constvolatile会被忽略,会出现拷贝

  4. 数组和函数会被退化为指针,除非ParamType为引用

2. auto类型推导

基本同模板推导:

  • auto&:第一种情况

  • auto&&:第二种情况

  • auto:第三种情况

但是{}下会被推导为std::initialize_list

auto作为返回值或者函数参数中,则采用模板的方案

3. decltype

简单返回表达式的类型,不会加以修改。

用于模板返回类型声明,而返回类型依赖参数类型:

  • decltype(auto)标注返回值类型,而不用auto那套推导方式

  • 或在函数后用-> decltype(...)标注返回值类型

此外,对于T类型但不是单纯变量名的左值,decltype总会会返回T&,所以用于decltype(auto)返回值声明时要小心。

4. 查看类型推导结果

4.1. IDE

可通过IDE传达推导的信息,例如CLion

4.2. 编译器诊断

可通过编译器的错误提示看到类型是什么

4.3. 运行时输出

类似typeidstd::type_info::name的方案,或用第三方库

typeid(T).name(), typeid(param).name()

实际上这些都不怎么可靠


Related Issues not found

Please contact @keys961 to initialize the comment


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK