作为对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引用形式参数调用构造函数。
在我看来,左值绑定(bind)到右值引用。一个glib答案可能是将左值转换为右值。但是问题是,这是一个编译器错误吗?如果不是,那么圣洁标准如何允许这样做?
编辑:我设法将其简化为以下非常简短的示例:
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-reference参数绑定(bind)到该临时值。如果您愿意,可以明确表示该转换:
void foo( double&& ) {} // pass-by-reference
int main()
{
char ch = '!';
foo( double(ch) );
}
但这在这种情况下并没有真正改变任何东西。如果
double
-> char
仅可以显式转换(例如,对于具有显式构造函数或显式转换运算符的类类型),但是double
到char
是有效的隐式转换,则这将是必要的。您正在考虑的“右值引用不能绑定(bind)到左值”规则是指将
T&&
绑定(bind)到T
左值,并且该规则没有被破坏,因为double&&
不绑定(bind)到char
,它绑定(bind)到了由隐式转换创建的临时目录。该规则不仅可以防止不必要的额外复制,而且还可以解决以前的规则中存在的实际安全问题,请参阅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<T>::push_back(T&&)
,并将该临时的移动到 vector 中。如果该push_back
重载对于转换结果不可行,则上面的代码将调用std::vector<T>::push_back(const T&)
,这将导致复制。当前的规则使这个实际的用例更加有效。如果规则说rvalue-refs无法绑定(bind)到隐式转换的结果,则您必须更改上面的代码以提高移动效率:v.push_back( std::string{"text"} );
恕我直言,当该构造函数不是显式的时,必须显式构造一个
std::string
是没有意义的。我希望显式/隐式构造函数具有一致的行为,并且我希望第一个push_back
示例更加有效。关于c++ - 将左值绑定(bind)到右值引用-G++错误?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12881209/