Effective Modern C++(1): 类型推导
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
为指针或引用
若ParamType
为T&
:
-
传入
int
:T = int
,ParamType = int&
-
传入
const int
:T = const int
,ParamType = const int&
-
传入
const int&
:T = const int
,ParamType = const int&
- 推导的
&
被忽略
- 推导的
若ParamType
为const T&
:
-
传入
int
:T = int
,ParamType = const int&
-
传入
const int
:T = int
,ParamType = const int&
- 推导的
const
被忽略
- 推导的
-
传入
const int&
:T = int
,ParamType = const int&
- 推导的
const
和&
都被忽略
- 推导的
对于指针(T*
与const T*
)也是一样
1.2. ParamType
为通用引用
即ParamType
为T&&
,可接受左值和右值:
-
若传入参数为左值(即可取地址),
T
和ParamType
会被推导为左值引用-
传入
int
:T = int&
(这里推导增加了引用),折叠后ParamType = int&
-
传入
const int
:T = const int&
(这里推导增加了引用),折叠后ParamType = const int&
-
传入
const int&
:T = const int&
,折叠后ParamType = const int&
-
-
若传入参数为右值,同第1节
- 传入
int
右值,如数字:T = int
,ParamType = int&&
- 传入
折叠规则:只要有左值引用,优先折叠为左值引用
& + & -> &
& + && -> &
&& + & -> &
&& + && -> &&
1.3. 传值
即ParamType
为T
。
-
若传入参数包含引用,引用被忽略,再忽略
const
和volatile
-
传入
int
,const int
,const int&
:T
和ParamType
都为int
-
这说明了传入的参数就是一个拷贝,和外面的无关了
-
若传入
const char* const
,拷贝了指针,但右边的const
被忽略,所以变成了指针可变、内容不可变
-
1.4. 数组
若ParamType
为T
- 若传入
int
数组,则会退化为const int*
指针
若ParamType
为T&
- 若传入
int
数组,则T
会推导为int[]
当然,更推荐直接使用std::array
1.5. 函数
会被退化为函数指针
1.6. 总结
-
若
ParamType
为T&
,传入引用时,推导会将引用忽略 -
若
ParamType
为T&&
,传入左值引用,会优先推导为左值引用 -
若
ParamType
为T
,引用、const
和volatile
会被忽略,会出现拷贝 -
数组和函数会被退化为指针,除非
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. 运行时输出
类似typeid
和std::type_info::name
的方案,或用第三方库
typeid(T).name()
,typeid(param).name()
实际上这些都不怎么可靠
Related Issues not found
Please contact @keys961 to initialize the comment
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK