左值的decltype括号语法

时间:2016-04-09 13:44:06

标签: c++ c++11 typetraits decltype

我正在尝试更好地理解 decltype ,以便在编译时确定表达式的类型。比方说,我用双变量来做:

#include <iostream>
#include <type_traits>

int main(){
    double a;
    typedef decltype(a) a_type;
    typedef decltype((a)) ref_a_type;
    typedef decltype(a)& o_ref_a_type;

    a_type b;
    ref_a_type c = b;
    o_ref_a_type d = b;

  if (std::is_same<decltype(b), double>::value) std::cout << "b is double\n";
  if (std::is_same<decltype(c), double&>::value) std::cout << "c is double&\n";
  if (std::is_same<decltype(d), double&>::value) std::cout << "d is double&\n";
}

如果我理解正确,这些要点应该是真的:

    如果decltype(a)是左值,则
  1. double&会返回a,否则会返回double
  2. decltype推导出表达式的类型,除非它应用于变量,在这种情况下它会推导出该变量的类型。
  3. 如果变量带括号,则变为左值表达式。
  4. 因此,decltype((a))decltype(a)&在这种情况下是等效的,但并不总是等效的,例如,如果a不是变量:

    typedef decltype((5)) ref_a_type;
    typedef decltype(5)& o_ref_a_type;
    

    然后两种类型都不相等(ref_a_typeinto_ref_a_typeint&,因为在这种情况下,额外的括号是无用的)。有人可以给出更好的解释吗?我应该使用第一种还是第二种方式? IMO似乎比第一种方式更具可读性和可理解性。

1 个答案:

答案 0 :(得分:6)

就C ++标准而言,decltype(e)的规则非常清楚,所以我只是复制它们(来自[dcl.type.simple]):

  

对于表达式edecltype(e)表示的类型定义如下:
  (4.1) - 如果e是未加密码的 id-expression 或未加密码的类成员访问(5.2.5),decltype(e)   是e命名的实体的类型。如果没有这样的实体,或者e命名一组重载函数,   该计划格式不正确;
  (4.2) - 否则,如果e是xvalue,decltype(e)T&&,其中Te的类型;
  (4.3) - 否则,如果e是左值,decltype(e)T&,其中T是e的类型;
  (4.4) - 否则,decltype(e)e的类型。

按顺序浏览你的例子:

  1. decltype(a)a是未加密码的 id-expression ,因此这只是a的类型:double
  2. decltype((a)):现在它有了括号,所以我们跳过了第一颗子弹。 a不是xvalue,它是左值,所以这是double&
  3. decltype(a)&:这只是第一个案例,所以它是double&
  4. decltype((5)):这既不是 id-expression (带括号或其他),xvalue或左值 - 所以我们放到最后一个项目符号来获取表达式:int
  5. decltype(5)&:与最后一点相同,除非您现在明确添加&,所以int&
  6.   

    我应该使用第一种还是第二种方式?

    这取决于您实际想要获得的类型。这两种方式意味着不同的东西 - 你应该用任何一种方法来解决你试图解决的直接问题。

    更一般地说,由于参考折叠规则,decltype(expr)& 总是左值参考。

    decltype((expr))可以是非引用(与decltype((5))一样),左值引用(与decltype((a))一样),也可以是右值引用(与decltype((std::move(a)))一样)