c++11 - std::move(a).m 是 xvalue 还是纯右值?

标签 c++11 c++14 decltype rvalue xvalue

假设 m 是非引用类型 (T) 的非静态数据成员。根据cppreference , std::move(a).m 在 c++11 之前是纯右值。我猜它应该是c++11之后的xvalue。如果我错了,请纠正我。

但是在 c++14 中,decltype(std::move(a).m) 仍然是 T (不是 T&&) (Visual Studio、Clang、GCC),这表明 std::move(a).m 仍然是纯右值。那么 std::move(a).m 是 xvalue 还是纯右值?

最佳答案

std::move(a).m 是一个 xvalue。

[basic.lval] 中的新措辞使这一点更加清晰:

  • A prvalue is an expression whose evaluation initializes an object or a bit-field, or computes the value of the operand of an operator, as specified by the context in which it appears.
  • An xvalue is a glvalue that denotes an object or bit-field whose resources can be reused (usually because it is near the end of its lifetime).

根据这些定义,std::move(a).m 是一个 xvalue,而不是纯右值,因为它表示一个对象。

我认为最好的思考方式是左值具有同一性并且右值可以安全地移动 - 左值具有同一性并且不能安全地移动,x值具有同一性并且可以安全地移动,而纯右值可以安全地移动。没有身份并且可以安全地离开。这种分类法使此类问题更容易推理。

此外[expr]中有一个注释,更具体:

[ Note: An expression is an xvalue if it is: [...]
— a cast to an rvalue reference to object type,
— a class member access expression designating a non-static data member of non-reference type in which the object expression is an xvalue, or [...]
—end note ]

std::move(a) 是对右值引用的强制转换,xvalue 也是如此。 std::move(a).m 是 xvalue 的类成员访问,xvalue 也是如此。

<小时/>

至于decltype(std::move(a).m)。请注意,该词本身来自已声明类型。 decltype(e) 含义的规则很复杂,来自 [dcl.type.simple]:

For an expression e, the type denoted by decltype(e) is defined as follows:
— if e is an unparenthesized id-expression naming an lvalue or reference introduced from the identifier-list of a decomposition declaration, decltype(e) is the referenced type as given in the specification of the decomposition declaration (8.5);
otherwise, if e is an unparenthesized id-expression or an unparenthesized class member access (5.2.5), decltype(e) is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed;
— otherwise, if e is an xvalue, decltype(e) is T&&, where T is the type of e;
— otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;
— otherwise, decltype(e) is the type of e.

在本例中,我们拥有类成员访问权限,因此您只需获取 m 的类型 - 即 M 而不是 M&& 。在某种程度上,这是有道理的,您要求 m 的声明类型,并且您得到了 m 的声明类型。

如果你想对其进行正确分类,你可以使用一组额外的括号强制忽略该项目符号(显然):decltype((std::move(a).m))会给你M&&

关于c++11 - std::move(a).m 是 xvalue 还是纯右值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42026327/

相关文章:

c++ - 仅使用 bool 和 char 定义模板类

c++ - 通过对常量的引用将元素传递给 lambda

c++11 - 无法运行 move 构造函数

c++ - 为什么不能从初始化列表初始化我的类,即使它是从 std::list 派生的?

C++ 正则表达式 : non-greedy match

c++ - 使用带有可变参数模板函数的 decltype 的尾随返回类型

c++ - 使用 decltype 获取表达式的类型,没有 const

c++ - 在 C++11 中初始化 C++ std::array of struct

c++ - 将推断类型传递给 std::find_if lambda 函数

c++ - 如何访问 integer_sequence 的第 n 个值?