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

后端 未结 2 833
一个人的身影
一个人的身影 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:54

    This looks like a Visual Studio bug. This comes down to the std::move and if we look at the cppreference page it has the following signature:

    template< class T >
    typename std::remove_reference::type&& move( T&& t );
    

    and it returns:

    static_cast::type&&>(t) 
    

    which matches the draft C++ standard section 20.2.4 forward/move helpers [forward].

    Using the code I grabbed from here we can see the following example:

    #include 
    
    template
    struct value_category {
        // Or can be an integral or enum value
        static constexpr auto value = "prvalue";
    };
    
    template
    struct value_category {
        static constexpr auto value = "lvalue";
    };
    
    template
    struct value_category {
        static constexpr auto value = "xvalue";
    };
    
    // Double parens for ensuring we inspect an expression,
    // not an entity
    #define VALUE_CATEGORY(expr) value_category::value
    
    
    int main()
    {   
        std::cout << VALUE_CATEGORY( static_cast::type&&>("") ) << std::endl ;
    
    }
    

    generates the following answer from gcc and clang using Wandbox:

    xvalue
    

    and this answer from Visual Studio using webcompiler:

    lvalue
    

    hence the error from Visual Studio for the original code:

    You cannot bind an lvalue to an rvalue reference

    when it attempt to bind the result of static_cast::type&&>(t) to std::remove_reference::type&& which is the return value of std::move.

    I don't see any reason why the static_cast should generate an lvalue as it does in the Visual Studio case.

提交回复
热议问题