假设m是非引用类型(T)的非静态数据成员。根据优先选择的说法,std::move(a).m是c++11之前的一个prvalue。我想它应该是c++11之后的xvalue。如果我错了,请纠正我。
但decltype(std::move(a).m)仍然是T (而不是T&&)在c++14 (视频工作室,clang,gcc),这表明std::move(a).m仍然是一个主要的价值。那么,std::move(a).m是xvalue还是prvalue?
发布于 2017-02-03 15:24:03
std::move(a).m是一个xvalue。
新的词语使这一点更加清晰,在basic.lval中。
根据这些定义,std::move(a).m是xvalue,而不是prvalue,因为它表示对象。
我认为最好的方式是,glvalue有标识,rvalue有标识,rvalue可以安全地移动--在这里,lvalue有标识,不安全地移动,xvalue有标识,可以安全地移动,而prvalue没有标识,可以安全地移动。这种分类法使这类问题更容易解释。
此外,expr中还有一个说明,更具体的是:
[注:表达式是xvalue,如果它是:. -转换为对对象类型的参考值, -一个类成员访问表达式,指定非引用类型的非静态数据成员,其中对象表达式为xvalue,或. -end注记]
std::move(a)是对rvalue的强制转换引用,xvalue也是。std::move(a).m是xvalue的类成员访问,xvalue也是。
至于decltype(std::move(a).m)。请注意,单词本身来自decl、ared类型。decltype(e)含义的规则很复杂,来自dcl.type.simple
对于表达式
e,由decltype(e)表示的类型定义如下: -如果e是一个无括号的id-表达式,命名从分解声明的标识符列表中引入的lvalue或引用,则decltype(e)是分解声明(8.5)的规范中给出的引用类型; -否则,如果decltype(e)是非括号的id-表达式或非括号的类成员访问(5.2.5),则 是e.命名的实体的类型。如果没有这样的实体,或者如果e命名了一组重载的函数,则程序是格式错误的; -否则,如果e是xvalue,则decltype(e)是T&&,其中T是e的类型; -否则,如果e是一个lvalue,则decltype(e)是T&,其中T是e的类型; -否则,decltype(e)是e的类型。
在本例中,我们有一个类成员访问权限,所以您只需要获得m的类型--即M,而不是M&&。在某种程度上,这是有意义的,您请求声明的m类型,并得到声明类型的m。
如果您想正确地对其进行分类,可以使用额外的括号(显然)来强制忽略该项目:decltype((std::move(a).m))会给您M&&。
https://stackoverflow.com/questions/42026327
复制相似问题