c++ - 物化纯右值成员访问的 decltype 行为不正确
问题描述
#include <iostream>
#include <type_traits>
struct A { double x; };
int main()
{
const A && a1 = A();
std::cout << std::is_same_v<decltype((a1.x)), const double&>;
std::cout << std::is_same_v<decltype((std::move(a1).x)), const double&&>;
std::cout << std::is_same_v<decltype((A().x)), double>;
}
Output:
111
不应该decltype在最后一个示例中返回double&&因为根据value categories。A().x是一个xvalue
极值
am,对象表达式的成员,其中 a 是右值,m 是非引用类型的非静态数据成员;
...
在 en.cppreference.com/w/cpp/language/decltype 的代码片段中使用 gcc7.1;gcc5.2;clang3.8;gcc4.9;gcc4.8;gcc4.7 测试
解决方案
严格按照标准,看来你是对的,应该是double &&
。我的推理链(所有引用来自 C++17 (n4659)):
8.2.5 类成员访问 [expr.ref]
1 后缀表达式后跟一个点
.
或箭头->
,可选地后跟关键字template
(17.2),然后是id-expression,是后缀表达式。...2 对于第一个选项(点),第一个表达式应是具有完整类类型的泛左值。
3将postfix-expression.id-expression缩写为
E1.E2
,E1
称为对象表达式。... 的类型和值类别E1.E2
确定如下。在 8.2.5 的其余部分中,cq表示或者const
不存在const
,vq表示或者volatile
不存在volatile
。cv表示任意一组 cv 限定符,如 6.9.3 中所定义。...
(4.2) if
E2
是非静态数据成员,类型E1
为“<em>cq1 vq1X
”,类型E2
为“<em>cq2 vq2T
”,表达式指定第一个指定的对象的命名成员表达。如果E1
是左值,那么E1.E2
是左值;否则E1.E2
是一个 xvalue。...
因此,如果 的左侧操作数.
是一个 xvalue,那么整个.
表达式的结果也是如此。
8.2.3 显式类型转换(函数表示法)[expr.type.conv]
1 一个简单类型说明符(10.1.7.2) 或类型名称说明符(17.6) 后跟一个带括号的可选表达式列表 或一个花括号初始化列表(初始化器)构造一个给定初始化器的指定类型的值。...
2 ...表达式是指定类型的纯右值,其结果对象使用初始化程序直接初始化(11.6)。
A()
prvalue也是如此。
最后:
8 个表达式 [expr]
10 每当一个纯右值表达式作为一个操作数的操作数出现时,该操作数需要一个左值,临时实现转换 (7.4) 用于将该表达式转换为一个 xvalue。
总之,这意味着这A()
是一个prvalue(来自8.2.3 / 2)。由于.
要求其 LHS 操作数是一个泛左值,因此应用了临时实现转换(每 8/10),结果是一个 xvalue。所以,从 8.2.5/(4.2) 开始,因为E1
是一个 xvalue,所以是E1.E2
,A().x
在你的情况下。
至于decltype
:
10.1.7.2 简单类型说明符 [dcl.type.simple]
4 对于表达式
e
,由 表示的类型decltype(e)
定义如下:...
(4.3) ...如果
e
是一个xvalue,decltype(e)
是T&&
,其中T
的类型是e
;
因为在你的情况下,(A().x)
被确定为一个 xvalue,它dectlype
应该是double &&
.
推荐阅读
- python - 使用唯一值子集数据框并返回每个唯一值的所有行
- python-3.x - ModuleNotFoundError:没有名为“djfilter.wsgi.application”的模块;'djfilter.wsgi' 不是一个包
- arrays - 如何将一个项目从一个阵列永久移动到另一个阵列?
- ruby-on-rails - Active Job 同时工作 - rails 5
- identityserver4 - 在 /connect/token 端点上出现 CORS 错误
- c++ - 如果在 CMakeLists.txt 中添加定义,Qt5 CMake 找不到 C++ STD 库
- react-native - 如何在 React Native LayoutAnimation 中为添加到平面列表顶部的项目设置动画
- c# - 使用 Microsoft.IdentityModel 进行 C#/.NET 5.0 SAML 签名验证
- java - 使用 ant 编译 Spring-Boot 应用程序时出错
- reactjs - 在 tableau server 或 tableau public 中显示全屏模式图标的 tableau-react 问题