zoukankan      html  css  js  c++  java
  • C++中decltype(*)作为模板实参时的隐藏问题

    在函数模板中使用智能指针时,可能会希望根据指针的类型推导出指针引用的对象类型作为模板参数,于是写出以下代码:
    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<>进行退化处理后再传入。

  • 相关阅读:
    单例模式的五种实现模式
    JAVA基础语法
    买卖股票的最佳时机 III
    leetcode 正则表达式 (动态规划)
    leetcode LRU缓存机制(list+unordered_map)详细解析
    leetcode 下一个排列(C++,STL源码解析)
    leetcode 编辑距离(动态规划)
    leetcode 字典序排数
    leetcode 字典序第K小数字
    leetcode 有效的括号(栈模拟)
  • 原文地址:https://www.cnblogs.com/Excr/p/12516095.html
Copyright © 2011-2022 走看看