可以reinterpret_cast(或任何演员)将xvalues转换为lvalue? [英] Can reinterpret_cast (or any cast) convert xvalues to lvalues?

查看:209
本文介绍了可以reinterpret_cast(或任何演员)将xvalues转换为lvalue?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码是否合法(通过C ++ 11和/或C ++ 14标准)?

Is the following code legal (by C++11 and/or C++14 standard(s))?

#include <iostream>
#include <utility>

using namespace std;

void foo(int &a) {
    cout << a << endl;
}

int main() {
    foo(reinterpret_cast<int &>(move(5)));
}




  • 如果是,是否未定义行为? / li>
  • 如果不是未定义的行为,我甚至可以在内<:code>它变成UB?

  • 它在clang 3.5上编译,而不是在gcc 4.9上编译。
    GCC错误:

    It compiles on clang 3.5, not on gcc 4.9. GCC error:

    ➤ 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)));
                                            ^
    



    EDIT



    FYI,一个定制的铸造,比以前更少毛,它工作在C ++ 11为GCC和Clang,将是以下 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;
    }
    


    推荐答案

    / strong>代码在C ++ 11中是不成形的。下面的答案是为C ++ 14。

    Update: The code is ill-formed in C++11. Answer below is for C++14. See note at the end of this answer.

    我相信此代码格式正确定义良好。这是为什么。

    I believe this code is both well-formed and well-defined. Here's why.

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

    The result of std::move is an xvalue [1], which is a type of glvalue; and converting a glvalue to an lvalue reference with reinterpret_cast appears to be allowed by the wording of the standard:


    类型 T1 的glvalue表达式可以转换为 T2 类型的引用if类型指针
    T1 的表达式可以显式转换为类型指向 T2 使用 reinterpret_cast 。结果将
    引用到与源glvalue相同的对象,但是具有指定的类型。 [注意:也就是说,对于左值,引用
    cast reinterpret_cast< T&>(x)具有与转换相同的效果 * reinterpret_cast< T *>(& x)
    内置& * 运算符(对于 reinterpret_cast< T&&>(x) - end note]没有创建临时
    ,没有创建副本,并且不调用构造函数(12.1)或转换函数(12.3)。

    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 也是允许的。该标准没有说明目标类型是否是一个左值引用或右值引用。

    Since "pointer to int" can be converted to "pointer to int", this reinterpret_cast is also allowed. The standard doesn't say anything about whether the destination type has to be an lvalue reference or rvalue reference.

    转换的结果是由上述段落:它引用与源glvalue相同的对象 - 即,值为 5的临时 int 对象。 ([dcl.init.ref]指定当一个prvalue绑定到一个引用时创建一个临时变量。)

    The result of the cast is well-defined by the paragraph above: it refers to the same object as the source glvalue---that is, a temporary int object with the value 5. ([dcl.init.ref] specifies that a temporary is created when a prvalue is bound to a reference.)

    通过 int& 也不违反任何别名规则,因为原始对象也是 int 类型。事实上,我相信,通过这样获得的左值来修改临时值也是很明确的。

    Accessing the value through the int& also doesn't violate any aliasing rules since the original object was also of type int. In fact I believe it would even be well-defined to modify the temporary through the lvalue thus obtained.

    注意:措辞表示左值表达式,而不是glvalue表达式。与glvalue expression的措辞是从N3936,这是C ++ 14的最后工作草案。我不是标准化过程如何工作的专家,但我相信这意味着左值到glvalue的变化已经被委员会投票,当ISO发布C ++ 14标准时,它会非常类似于上面所说的。

    Note: The C++11 wording says "lvalue expression", not "glvalue expression". The wording with "glvalue expression" is from N3936, which is the final working draft for C++14. I'm not an expert in how the standardization process works, but I believe this means that the change of "lvalue" to "glvalue" was already voted in by the committee, and when ISO publishes the C++14 standard, it's going to be pretty similar to what it says above.

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

    [1] Except in the rare case in which the argument is a function; in that case the result is an lvalue, since there are no function rvalues.

    这篇关于可以reinterpret_cast(或任何演员)将xvalues转换为lvalue?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆