std ::移动字符串文字 - 哪个编译器是正确的? [英] std::move of string literal - which compiler is correct?

查看:109
本文介绍了std ::移动字符串文字 - 哪个编译器是正确的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出以下代码:

  #include< string& 
void foo()
{
std :: string s(std :: move());
}

这是用apple clang(xcode 7)编译的,它产生以下错误:

 错误C2440:'return':无法从'const char [1]'转换为'const char(&&)[1]'
注意:你不能将一个左值绑定到一个右值引用
main.cpp(4):note: ;& std :: move< const char(&)[1]>(_ Ty)noexcept)[1]'正在编译
with
[
_Ty = const char ;)[1]
]

忽略移动是多余的标准库实现在这种情况下更正确吗?



我的感觉是 code> const char [1] 因此 std :: move 应该返回 std :: remove_reference< [1]&> :: type&&& 这将是 const char [1]&&

在我看来,这应该衰减到 const char *



或者我是否误解规则?

解决方案

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

  template<类T> 
typename std :: remove_reference< T> :: type&&&移动(T& T);

并返回:

  static_cast< typename std :: remove_reference< T> :: type&&>(t)

它符合草稿C ++标准节 20.2.4 转发/移动助手[forward]。



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

  #include< iostream> 

template< typename T>
struct value_category {
//或者可以是一个积分或枚举值
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;
}

//用于确保检查表达式的双括号,
//不是实体
#define VALUE_CATEGORY(expr)value_category< decltype((expr))> ::值


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

}

使用 Wandbox

  xvalue 

这个答案来自Visual Studio使用 webcompiler

  lvalue 

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


当试图绑定的结果时,不能将左值绑定到右值引用




< static_cast< typename std :: remove_reference< T> :: type&&>(t)
std :: remove_reference& code>这是 std :: move 的返回值。



为什么 static_cast 应该像Visual Studio中那样生成一个左值。


Given the following code:

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

This compiles with apple clang (xcode 7) and does not with visual studio 2015 which generates the following error:

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]
    ]

Ignoring for the moment that the move is redundant, which standard library implementation is the more correct in this case?

My feeling is that the type of "" is const char[1] so std::move should return std::remove_reference<const char[1]&>::type&& which would be const char[1]&&.

It seems to me that this should decay to const char*.

Or do I misunderstand the rules?

解决方案

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<T>::type&& move( T&& t );

and it returns:

static_cast<typename std::remove_reference<T>::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 <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 ;

}

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<typename std::remove_reference<T>::type&&>(t) to std::remove_reference<T>::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.

这篇关于std ::移动字符串文字 - 哪个编译器是正确的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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