加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 绑定左值给rvalue引用 – g bug?

发布时间:2020-12-16 05:48:24 所属栏目:百科 来源:网络整理
导读:作为 another question的答案,我想发布以下代码(也就是说,我想根据这个想法发布代码): #include iostream#include utility // std::is_same,std::enable_ifusing namespace std;template class Type struct Boxed{ Type value; template class Arg Boxed( A
作为 another question的答案,我想发布以下代码(也就是说,我想根据这个想法发布代码):
#include <iostream>
#include <utility>      // std::is_same,std::enable_if
using namespace std;

template< class Type >
struct Boxed
{
    Type value;

    template< class Arg >
    Boxed(
        Arg const& v,typename enable_if< is_same< Type,Arg >::value,Arg >::type* = 0
        )
        : value( v )
    {
        wcout << "Generic!" << endl;
    }

    Boxed( Type&& v ): value( move( v ) )
    {
        wcout << "Rvalue!" << endl;
    }
};

void function( Boxed< int > v ) {}

int main()
{
    int i = 5;
    function( i );  //<- this is acceptable

    char c = 'a';
    function( c );  //<- I would NOT like this to compile
}

但是,MSVC 11.0在最后一次调用时会阻塞,因为IHMO应该使用,MinGW g 4.7.1只是接受它,并使用rvalue引用形式参数调用构造函数.

它看起来好像一个左值被绑定到一个右值引用. glib答案可能是左值被转换为rvalue.但问题是,这是一个编译器的错误,如果不是,圣标是如何允许的?

编辑:我设法把它全部缩小到以下很简单的例子:

void foo( double&& ) {}

int main()
{
    char ch = '!';
    foo( ch );
}

无法使用MSVC 11.0进行编译,是否与MinGW 4.7.1进行编译,是对吗?

解决方法

大概你同意这是有效的?
void foo( double ) {}  // pass-by-value

int main()
{
    char ch = '!';
    foo( ch );
}

有一个从char到double的隐式转换,所以函数是可行的.

在编辑的问题的示例中是一样的,存在一个隐式转换,产生一个临时的(即rvalue),并且rvalue引用参数绑定到该临时值.如果您愿意,您可以将该转换显式显示:

void foo( double&& ) {}  // pass-by-reference

int main()
{
    char ch = '!';
    foo( double(ch) );
}

但是在这种情况下这并不会改变任何事情.这将是必要的,如果双重 – > char只能被显式转换(例如对于具有显式构造函数或显式转换运算符的类类型),而char的double是有效的隐式转换.

你认为的“一个价值参考不能绑定到一个左值”规则是指绑定一个T&&这个规则并不破坏,因为双重&不绑定到char,它绑定到一个临时创建的隐式转换.

该规则不仅存在,以防止不必要的额外复制,而是修复与以前规则存在的真实安全问题,请参见http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2812.html

编辑:有人问这个行为是否适合委员会反思(见DR 1414),并且决定是的,这个行为是有意义的,是正确的.用于达成这一职位的一个参数是,使用当前规则,此代码更有效:

std::vector<std::string> v;
v.push_back("text");

使用当前规则,通过隐式转换创建临时std :: string,然后调用std :: vector> :: push_back(T&&),并将临时移动到向量中.如果push_back重载对于转换的结果是不可行的,则上面的代码将调用将导致副本的std :: vector> :: push_back(const T&).目前的规则使这个现实世界的用例更加高效.如果规则表明rvalue-refs不能绑定到隐式转换的结果,您将不得不更改上述代码以获得移动效率:

v.push_back( std::string{"text"} );

当这个构造函数不是显式的时候,IMHO不必明确地构造一个std :: string.我想要显式/隐式构造函数的一致行为,我希望第一个push_back示例更有效率.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读