标签:编译器 通过 float erro var 模板 处理 区分 c++
在函数模板中使用智能指针时,可能会希望根据指针的类型推导出指针引用的对象类型作为模板参数,于是写出以下代码: shared_ptr<decltype(*objPtr)>(objPtr);
一眼看上去似乎是正确的,然而实际上隐藏着一个问题会导致错误,这要从decltype()
推断出的类型说起。
decltype(a)
推断出的类型a
为变量a
的类型T
。 int a = 0;
decltype(a) b; //(int) b
a
为右值表达式a
的类型T
。 decltype(2.f) b; //(float) b
decltype(b + 1) c; //(float) c
a
为左值表达式decltype
推断出的类型是a
的引用类型T&
;,这也正是造成前文所述问题的根源。 int b = 0;
decltype(*(&b)) c; //error: declaration of reference variable ‘c‘ requires an initializer
回到刚才说的shared_ptr
的例子,假设objPtr
的类型为T
,decltype(*objPtr)
被推断为T&
,但shared_ptr
的模板实参应为T
,所以产生了错误。想要解决这个问题,方法之一是使用std::decay<>
std::decay<>
的使用std::decay<>
可以把类型的各种修饰(cosnt T, T&
, etc.)退化,仅返回基本类型T
(或T*
,T*
是不会被退化为T
的)。
将std::decay
应用于前文的代码,得到:
shared_ptr<typename std::decay<decltype(*objPtr)>::type>(objPtr);
注意typename
关键字是不能省的,因为编译器无法区分std::decay<decltype(*objPtr)>
的type
成员到底是变量还是类型。
为了方便理解,本文以函数模板中shared_ptr
的使用作为例子;但实际上这个问题可以推广到任何希望以decltype(*)
作为模板实参时的场景:如果模板的实参并非T&
,就必须通过std::decay<>
进行退化处理后再传入。
标签:编译器 通过 float erro var 模板 处理 区分 c++
原文地址:https://www.cnblogs.com/Excr/p/12516095.html