c++ - reinterpret_cast(或任何强制转换)可以将 xvalues 转换为 lvalues 吗?

标签 c++ c++11 language-lawyer c++14 reinterpret-cast

以下代码是否合法(根据 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)));
}
  • 如果是,是否是未定义的行为?
  • 如果这不是未定义的行为,我什至可以改变 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)));
                                        ^

编辑

仅供引用,一个定制的类型转换比以前更简单,并且适用于 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;
}

最佳答案

更新:代码在 C++11 中格式错误。以下答案适用于 C++14。请参阅此答案末尾的注释。

我相信这段代码既格式良好定义良好。原因如下。

std::move 的结果是一个 xvalue [1],它是一种 glvalue;并使用 reinterpret_cast 将左值转换为左值引用标准的措辞似乎是允许的:

A glvalue expression of type T1 can be cast to the type “reference to T2” if an expression of type “pointer to T1” can be explicitly converted to the type “pointer to T2” using a reinterpret_cast. The result refers to the same object as the source glvalue, but with the specified type. [ Note: That is, for lvalues, a reference cast reinterpret_cast<T&>(x) has the same effect as the conversion *reinterpret_cast<T*>(&x) with the built-in & and * operators (and similarly for reinterpret_cast<T&&>(x)). — end note ] No temporary is created, no copy is made, and constructors (12.1) or conversion functions (12.3) are not called.73

因为“指向int的指针”可以转换为“指向int的指针”,所以这个reinterpret_cast也是允许的。该标准没有说明目标类型必须是左值引用还是右值引用。

转换的结果由上面的段落明确定义:它指的是与源泛左值相同的对象——即一个临时的int。值为 5 的对象. ([dcl.init.ref] 指定当纯右值绑定(bind)到引用时创建一个临时文件。)

通过 int& 访问值也不违反任何别名规则,因为原始对象的类型也是 int .事实上,我相信通过由此获得的左值修改临时值甚至是明确定义的。

注意:C++11 的措辞是“左值表达式”,而不是“左值表达式”。带有“glvalue expression”的措辞来自 N3936,这是 C++14 的最终工作草案。我不是标准化过程如何运作的专家,但我相信这意味着委员会已经投票通过了将“左值”更改为“左值”,并且当 ISO 发布 C++14 标准时,它将会与上面所说的非常相似。

[1] 参数是函数的极少数情况除外;在这种情况下,结果是一个左值,因为没有函数右值。

关于c++ - reinterpret_cast(或任何强制转换)可以将 xvalues 转换为 lvalues 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26793072/

相关文章:

c++ - 子进程的主要功能

c++ - Leetcode 1423:如何优化暴力递归方法?

c++ - 创建用于创建和打印 vector 的 C++ 类对象

c++ - 如果表达式的求值需要对引用求值,为什么表达式不是 "core constant expression"?

gcc - 如何在MacPorts gcc 4.5中调试C++ 0x程序?

c - 结构类型的完成是否对同一范围内该类型的所有先前声明有效?

c++ - 无法将模板参数传递给 std::list<T>::iterator

c++ - 使用结构作为映射中的键

c++ - vector::insert 是否只允许保留一次并避免进一步的容量检查?

c - 鉴于 p 是指向不完整类型的指针,&*p 是有效的 C 语言吗?