【问题标题】:Why is a variable not an lvalue in C++?为什么 C++ 中的变量不是左值?
【发布时间】:2019-07-31 07:07:50
【问题描述】:
#include <type_traits>

int main()
{    
    int n;
    n = 0;

    // failure!
    static_assert(std::is_lvalue_reference_v<decltype(n)>); 
}

n 可以放在左边,所以显然应该是左值。

为什么static_assert 会失败?

【问题讨论】:

标签: c++ c++11 standards typetraits


【解决方案1】:

decltype 对 id-expressions 有特殊的规则,在不考虑值类别的情况下推断它们的类型。如果您希望它根据 id-expression 通常具有的值类别推断类型,可以将 id-expression 括在括号中:

static_assert(std::is_lvalue_reference_v<decltype((n))>); 

(n) 在类型系统中与n 具有相同的类型和值类别,但没有被decltype 特殊处理。由于表达式是左值,推导的类型将是左值引用类型。

【讨论】:

  • 这让我很困惑,我知道n 是一个左值,但它怎么是一个左值reference?如果我创建一个int &amp; j 那会是什么左值呢?
  • @Frodyne - 这不是左值引用,而是int。但是n 也是一个表达式,作为一个表达式,它有一个类型和一个值类别。它的值类别是一个左值。到目前为止一切顺利,但decltype 试图将值类别折叠到推导类型中。对于T 类型的左值表达式,它将提供T&amp; 类型。
  • decltype(auto) f() { int n; return (n); } 返回一个(悬空)引用。这是否相关?如果相关,如何?
  • @Aconcagua - 这是相关的。 decltype(auto)return expr; 中的expr 推导出返回类型。由于它是带括号的,因此它使用为大多数左值表达式推导引用类型的规则。如果它没有括号,它会使用 id-expressions 的特殊规则,只给出它们声明的类型。
  • 嗯,一直认为括号中的情况是“特殊情况”???您能否提供一个具体示例,即使左值本身不是一个,即使左值本身不是一个(@Frodyne 的回复中的T&amp;),非括号参数也会产生引用?
【解决方案2】:

n确实是一个左值引用,但decltype(n)返回int,而不是int&amp;。这种机制基于模板类型推导的工作方式。它允许您进行这样的声明和初始化:

int n = 0;

decltype(n) m = 42;

如果decltype(n) 产生int&amp;,上面的sn-p 甚至不会编译。因此,您可以使编译器满意

static_assert(std::is_lvalue_reference_v<decltype(n)&>); 
static_assert(std::is_lvalue_reference_v<std::add_lvalue_reference_t<decltype(n)>>); 

但我想这不是重点。

【讨论】:

    猜你喜欢
    • 2020-07-11
    • 2019-07-06
    • 2015-02-06
    • 1970-01-01
    • 2012-11-17
    • 1970-01-01
    • 2015-12-13
    • 1970-01-01
    相关资源
    最近更新 更多