给定以下代码:
#include <string>
void foo()
{
std::string s(std::move(""));
}
这可以使用 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]
]
暂时忽略移动是多余的,在这种情况下哪个标准库实现更正确?
我的感觉是 ""
的类型是 const char[1]
所以std::move
应该返回 std::remove_reference<const char[1]&>::type&&
这将是 const char[1]&&
.
在我看来,这应该衰减到 const char*
.
还是我误解了规则?
最佳答案
这看起来像一个 Visual Studio 错误。这归结为 std::move如果我们查看 cppreference 页面,它具有以下签名:
template< class T >
typename std::remove_reference<T>::type&& move( T&& t );
然后它返回:
static_cast<typename std::remove_reference<T>::type&&>(t)
符合草案 C++ 标准部分 20.2.4
前进/移动助手[前进]。
使用 code I grabbed from here我们可以看到下面的例子:
#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 ;
}
使用 Wandbox 从 gcc 和 clang 生成以下答案:
xvalue
这个答案来自 Visual Studio 使用 webcompiler :
lvalue
因此来自 Visual Studio 的原始代码错误:
You cannot bind an lvalue to an rvalue reference
当它试图绑定(bind) static_cast<typename std::remove_reference<T>::type&&>(t)
的结果时至std::remove_reference<T>::type&&
这是std::move
的返回值.
我看不出 static_cast
的任何原因应该像在 Visual Studio 案例中那样生成一个左值。
关于c++ - 字符串文字的 std::move - 哪个编译器是正确的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34160614/