std::move of string literal - which compiler is correct?

后端 未结 2 830
一个人的身影
一个人的身影 2021-01-07 17:01

Given the following code:

#include 
void foo()
{
  std::string s(std::move(\"\"));
}

This compiles with apple clang (xcode 7)

2条回答
  •  隐瞒了意图╮
    2021-01-07 17:50

    Let's start by breaking this up into two pieces, so we can analyze each separately:

    #include 
    void foo()
    {
        auto x = std::move("");
        std::string s(x);
    }
    

    The second part, that initializes the string from x (whatever type that might happen to be) isn't really the problem or question at hand here. The question at hand (at least as it seems to me) is the first line, where we try to bind an rvalue reference to a string literal.

    The relevant part of the standard for that would be [dcl.init.ref]/5 (§8.5.3/5, at least in most versions of the C++ standard I've seen).

    This starts with:

    A reference to type ''cv1 T1'' is initialized by an expression of type ''cv2 T2'' as follows.

    That's followed by a bullet list. The first item covers only lvalue references, so we'll ignore it. The second item says:

    if the initializer expression
    - is an xvalue (but not a bit-field) class prvalue, array prvalue or function lvalue[...]
    - has class type (i.e., T2 is a class type)[...]
    - Otherwise - if T1 or T2 is a class type and T1 is not is not reference related to T2 [...]

    Clearly none of those applies. A string literal is not an xvalue, class prvalue, array prvalue or function lvalue, nor does it have class type.

    That leaves only:

    If T1 is reference-related to T2:
    - cv1 shall be the same cv-qualification as, or greater cv-qualification than, cv2, and
    - if the reference is an rvalue reference, the initializer expression shall not be an lvalue.

    Since, in this case, the type of the result of the conversion is being deduced by the compiler, it will be reference-related to type of the initializer. In this case, as the part I've emphasized says, the initializer expression can't be an lvalue.

    That leaves only the question of whether a string literal is an lvalue. At least offhand, I can't immediately find the section of the C++ standard that says they are (there's no mention of it in the section on string literals). If it's absent, the next step would be to look at the base document (the C standard) which clearly states that string literals are lvalues (N1570, §6.5.1/4)

    A string literal is a primary expression. It is an lvalue with type as detailed in 6.4.5.

    I do wish I could find a direct statement to that effect in the C++ standard (I'm pretty sure it should exist), but for whatever reason I'm not finding it right now.

提交回复
热议问题