J. *_*Doe 8 c++ language-lawyer c++11 c++14
该计划格式不正确:
struct X { int i; };
int main() {
(X { }).i = 1;
}
Run Code Online (Sandbox Code Playgroud)
i,临时的子对象X { },不能用作左值,因为它 X { }是一个右值.
但是,这默默地编译了GCC 5.2.1和-Wall:
using Y = int[10];
int main() {
(Y { })[0] = 1;
}
Run Code Online (Sandbox Code Playgroud)
如果编译器是正确的,那么这次,(Y { })作为子对象的第0个元素(Y { })可以被视为左值.
我的问题是:
我相信第二个案例是不正确的,如果我正确地阅读缺陷报告1213,它说:
因为下标操作被定义为通过指针值的间接,所以应用于xvalue数组的下标运算符的结果是左值,而不是x值.对某些人来说这可能是令人惊讶的.
并且解决方案是对C++标准部分5.2.1 [expr.sub]的草案进行了以下更改,(添加了粗体部分并删除了删除线):
后缀表达式后跟方括号中的表达式是后缀表达式.其中一个表达式应具有"T的数组"类型 或 "指向T的指针",另一个表达式应具有未映射的枚举或整数类型.结果是类型"T"
的左值.类型"T"应该是完全定义的对象类型.62表达式E1 [E2]是相同的(根据定义)到*((E1)+(E2))[注意:有关数组的详细信息,请参阅5.3 [expr.unary]和5.7 [expr.add]以获取*和+和8.3.4 [dcl.array]的详细信息.-end note] ,除了在数组操作数的情况下,如果该操作数是左值,则结果为左值,否则为x值.
结果Y{}是来自5.2.3 [expr.type.conv]部分的prvalue :
类似地,一个simple-type-specifier或typename-specifier后跟一个braced-init-list,用指定的braced-init-list创建一个指定类型direct-list-initialized(8.5.4)的临时对象及其值是 临时对象作为prvalue.
所以结果(Y { })[0]应该是一个xvalue,因此格式不正确,因为赋值需要在左操作数上有一个可修改的左值:
赋值运算符(=)和复合赋值运算符都是从右到左分组.所有都需要一个可修改的左值作为他们的左操作数[...]
我们可以从C++ 14标准草案中的缺陷报告中找到更新的措辞 ,因此这个更改在C++ 11之后应用,但可能适用于C++ 11,因为这是通过缺陷报告应用的.
为什么部分5.3.1 [expr.unary.op]没有更新我不清楚,似乎有些不一致的说结果是左值,它并非在所有情况下.
更新
提起了一个clang bug报告.
| 归档时间: |
|
| 查看次数: |
553 次 |
| 最近记录: |