pep*_*ico 8 c++ language-lawyer reinterpret-cast c++11 c++14
以下代码是否合法(通过C++ 11和/或C++ 14标准)?
#include <iostream>
#include <utility>
using namespace std;
void foo(int &a) {
cout << a << endl;
}
int main() {
foo(reinterpret_cast<int &>(move(5)));
}
Run Code Online (Sandbox Code Playgroud)
a在foo没有变成UB的情况下进行变异吗?它在clang 3.5上编译,而不是在gcc 4.9上编译.GCC错误:
? g++-4.9 -std=c++1y sample.cpp -o sample
sample.cpp: In function 'int main()':
sample.cpp:11:40: error: invalid cast of an rvalue expression of type 'std::remove_reference<int>::type {aka int}' to type 'int&'
foo(reinterpret_cast<int &>(move(5)));
^
Run Code Online (Sandbox Code Playgroud)
仅供参考,一个定制的演员阵容,比以前更少毛茸茸,并且适用于GCC和Clang的C++ 11,它将具有以下lvalue功能:
#include <iostream>
namespace non_std {
template <typename T>
constexpr T &lvalue(T &&r) noexcept { return r; }
}
void divs(int &a, int &b) {
int t = a;
a /= b;
b /= t;
}
int main() {
using namespace std;
using namespace non_std;
int i_care_for_this_one = 4;
divs(i_care_for_this_one, lvalue(2));
cout << i_care_for_this_one << endl;
}
Run Code Online (Sandbox Code Playgroud)
更新:代码在C++ 11中格式不正确.以下答案适用于C++ 14.请参阅本答案末尾的注释.
我相信这段代码既有良好的形式,也有明确的定义.这就是原因.
结果std::move是xvalue [1],它是一种glvalue; 并且将glvalue转换为左值引用reinterpret_cast似乎是标准的措辞所允许的:
如果类型"指向" 的表达式可以使用a 显式转换为"指向" 的类型,则
T1可以将类型的glvalue表达式强制转换为"引用T2"类型.结果引用与源glvalue相同的对象,但具有指定的类型.[注意:也就是说,对于左值,参考演员与使用内置和运算符的转换具有相同的效果(同样适用于). - 尾注]没有创建临时,没有复制,并且没有调用构造函数(12.1)或转换函数(12.3).73T1T2reinterpret_castreinterpret_cast<T&>(x)*reinterpret_cast<T*>(&x)&*reinterpret_cast<T&&>(x)
由于"指向"的指针int可以转换为"指向int",因此reinterpret_cast也允许这样做.该标准没有说明目标类型是否必须是左值引用或右值引用.
转换的结果由上面的段落明确定义:它引用与源glvalue相同的对象---即int具有值的临时对象5.([dcl.init.ref]指定在将prvalue绑定到引用时创建临时.)
通过它访问值int&也不违反任何别名规则,因为原始对象也是类型int.事实上,我相信甚至可以通过如此获得的左值来修改临时值.
注意: C++ 11的措辞是"左值表达式",而不是"glvalue表达式".带有"glvalue表达式"的措辞来自N3936,这是C++ 14的最终工作草案.我不是标准化过程如何工作的专家,但我相信这意味着"左值"到"glvalue"的变化已经被委员会投票,当ISO发布C++ 14标准时,它就会出现与上面说的很相似.
[1]除了极少数情况下,论证是一个函数; 在这种情况下,结果是左值,因为没有函数rvalues.
小智 5
问题在于是否允许reinterpret_cast将xvalues转换为lvalues.与其他人粘贴的内容相反,相关段落(5.2.10.11)仅提到左值:
如果可以使用reinterpret_cast将"指向T1的指针"类型的表达式显式转换为"指向T2的指针"类型,则可以将类型T1的左值表达式强制转换为"对T2的引用"类型.
迈克尔·黄提交了一份提案,要求将措辞改为glvalue,但它似乎已经碰壁了:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1268
我认为这意味着,截至目前,转换不合法,因为它只明确允许从左值转换.
| 归档时间: |
|
| 查看次数: |
993 次 |
| 最近记录: |