【问题标题】:decltype parenthesis syntax for a lvalue左值的 decltype 括号语法
【发布时间】:2016-04-09 13:44:05
【问题描述】:

我试图更好地理解 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";
}

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

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

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

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

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

【问题讨论】:

  • 如果T是非引用类型,那么decltype(f())TT&amp;T&amp;&amp;分别对应T f();T&amp; f();T&amp;&amp; f();

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


【解决方案1】:

就 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&amp;&amp;,其中 Te 的类型;
(4.3) — 否则,如果e 是左值,则decltype(e)T&amp;,其中T 是e 的类型;
(4.4) — 否则,decltype(e)e 的类型。

所以按顺序浏览你的例子:

  1. decltype(a):a 是一个没有括号的id-expression,所以这只是a:double 的类型。
  2. decltype((a)):现在是括号,所以我们跳过第一个项目符号。 a 不是 xvalue,它是 lvalue,所以这是 double&amp;
  3. decltype(a)&amp;:这又是第一个案例,所以是double&amp;
  4. decltype((5)):这既不是 id-expression(括号或其他)、xvalue 或左值 - 它是 prvalue,所以我们转到最后一个项目符号来获取表达式的类型:int
  5. decltype(5)&amp;:与最后一点相同,只是现在您明确添加了&amp;,所以int&amp;

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

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

更一般地说,decltype(expr)&amp;总是由于引用折叠规则而成为左值引用。

decltype((expr)) 可以是非引用纯右值(如decltype((5)))、左值引用(如decltype((a)))或右值引用(如decltype((std::move(a))))。

【讨论】:

    猜你喜欢
    • 2011-03-07
    • 2012-12-16
    • 1970-01-01
    • 2020-06-08
    • 2020-11-18
    • 1970-01-01
    • 1970-01-01
    • 2016-01-17
    相关资源
    最近更新 更多