码迷,mamicode.com
首页 > 编程语言 > 详细

C++中decltype(*)作为模板实参时的隐藏问题

时间:2020-03-18 11:18:27      阅读:95      评论:0      收藏:0      [点我收藏+]

标签:编译器   通过   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的类型为Tdecltype(*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<>进行退化处理后再传入。

C++中decltype(*)作为模板实参时的隐藏问题

标签:编译器   通过   float   erro   var   模板   处理   区分   c++   

原文地址:https://www.cnblogs.com/Excr/p/12516095.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!