#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示例更有效率.