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

前端之家收集整理的这篇文章主要介绍了c – 绑定左值给rvalue引用 – g bug?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
作为 another question的答案,我想发布以下代码(也就是说,我想根据这个想法发布代码):
  1. #include <iostream>
  2. #include <utility> // std::is_same,std::enable_if
  3. using namespace std;
  4.  
  5. template< class Type >
  6. struct Boxed
  7. {
  8. Type value;
  9.  
  10. template< class Arg >
  11. Boxed(
  12. Arg const& v,typename enable_if< is_same< Type,Arg >::value,Arg >::type* = 0
  13. )
  14. : value( v )
  15. {
  16. wcout << "Generic!" << endl;
  17. }
  18.  
  19. Boxed( Type&& v ): value( move( v ) )
  20. {
  21. wcout << "Rvalue!" << endl;
  22. }
  23. };
  24.  
  25. void function( Boxed< int > v ) {}
  26.  
  27. int main()
  28. {
  29. int i = 5;
  30. function( i ); //<- this is acceptable
  31.  
  32. char c = 'a';
  33. function( c ); //<- I would NOT like this to compile
  34. }

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

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

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

  1. void foo( double&& ) {}
  2.  
  3. int main()
  4. {
  5. char ch = '!';
  6. foo( ch );
  7. }

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

解决方法

大概你同意这是有效的?
  1. void foo( double ) {} // pass-by-value
  2.  
  3. int main()
  4. {
  5. char ch = '!';
  6. foo( ch );
  7. }

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

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

  1. void foo( double&& ) {} // pass-by-reference
  2.  
  3. int main()
  4. {
  5. char ch = '!';
  6. foo( double(ch) );
  7. }

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

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

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

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

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

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

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

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

猜你在找的C&C++相关文章