std :: move of string literal - 哪个编译器正确?

Ric*_*ges 27 c++ language-lawyer visual-studio-2015

给出以下代码:

#include <string>
void foo()
{
  std::string s(std::move(""));
}
Run Code Online (Sandbox Code Playgroud)

这与apple clang(xcode 7)编译,而不是与visual studio 2015生成以下错误:

error C2440: 'return': cannot convert from 'const char [1]' to 'const char (&&)[1]'
note: You cannot bind an lvalue to an rvalue reference
main.cpp(4): note: see reference to function template instantiation 'const char (&&std::move<const char(&)[1]>(_Ty) noexcept)[1]' being compiled
    with
    [
        _Ty=const char (&)[1]
    ]
Run Code Online (Sandbox Code Playgroud)

暂时忽略移动是多余的,在这种情况下哪个标准库实现更正确?

我的感觉是该类型即""const char[1]如此std::move应该返回std::remove_reference<const char[1]&>::type&&这将是const char[1]&&.

在我看来,这应该衰败const char*.

或者我是否误解了这些规则?

Sha*_*our 11

这看起来像Visual Studio错误.这归结为std :: move,如果我们查看cppreference页面,它具有以下签名:

template< class T >
typename std::remove_reference<T>::type&& move( T&& t );
Run Code Online (Sandbox Code Playgroud)

它返回:

static_cast<typename std::remove_reference<T>::type&&>(t) 
Run Code Online (Sandbox Code Playgroud)

这与草案C++标准部分20.2.4前进/移动助手[前进] 相匹配.

使用我从这里抓取代码,我们可以看到以下示例:

#include <iostream>

template<typename T>
struct value_category {
    // Or can be an integral or enum value
    static constexpr auto value = "prvalue";
};

template<typename T>
struct value_category<T&> {
    static constexpr auto value = "lvalue";
};

template<typename T>
struct value_category<T&&> {
    static constexpr auto value = "xvalue";
};

// Double parens for ensuring we inspect an expression,
// not an entity
#define VALUE_CATEGORY(expr) value_category<decltype((expr))>::value


int main()
{   
    std::cout << VALUE_CATEGORY( static_cast<std::remove_reference<const char[1]>::type&&>("") ) << std::endl ;

}
Run Code Online (Sandbox Code Playgroud)

使用Wandbox从gcc和clang生成以下答案:

xvalue
Run Code Online (Sandbox Code Playgroud)

以及使用webcompiler从Visual Studio获得的答案:

lvalue
Run Code Online (Sandbox Code Playgroud)

因此Visual Studio对原始代码的错误:

您不能将左值绑定到右值引用

当它试图绑定结果时static_cast<typename std::remove_reference<T>::type&&>(t),std::remove_reference<T>::type&&返回值为std::move.

我没有看到为什么static_cast应该像在Visual Studio案例中那样生成左值的原因.