左值的decltype括号语法

Fra*_*101 6 c++ decltype type-traits c++11

我正在尝试更好地理解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";
}
Run Code Online (Sandbox Code Playgroud)

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

  1. decltype(a)double&如果a是左值double则返回,否则返回.
  2. decltype推导出表达式的类型,除非将其应用于变量,在这种情况下,它会推导出该变量的类型.
  3. 如果变量带括号,则它变为左值表达式.

因此,decltype((a))decltype(a)&是相等的在这种情况下,但并不总是相等的,例如,如果a是不是一个变量:

typedef decltype((5)) ref_a_type;
typedef decltype(5)& o_ref_a_type;
Run Code Online (Sandbox Code Playgroud)

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

Bar*_*rry 6

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

对于表达式e,表示的类型decltype(e)定义如下:
(4.1) - 如果e是未加密码的id-expression或未加密的类成员访问(5.2.5),decltype(e) 则是名为的实体的类型e.如果没有这样的实体,或者如果e命名了一组重载函数,那么该程序就会形成错误;
(4.2) - 否则,如果e是x值,decltype(e)则是T&&,T其类型e;
(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表达式(括号或其他),xvalue或左值 - 所以我们放到最后一个子弹来获取表达式的类型:int.
  5. decltype(5)&:与最后一点相同,除了现在你明确添加一个&,所以int&.

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

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

更一般地,decltype(expr)&总是由于参考倒塌规则左值参考.

decltype((expr))可以是非引用(如同decltype((5))),左值引用(如同decltype((a)))或右值引用(如同decltype((std::move(a)))).