Che*_*Alf 10 c++ compiler-errors
作为另一个问题的答案,我想发布以下代码(也就是说,我想根据这个想法发布代码):
#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
}
Run Code Online (Sandbox Code Playgroud)
然而,虽然MSVC 11.0在最后一次通话扼流圈,因为它IHMO应MinGW的G ++ 4.7.1只是被动地接受它,并调用与右值引用形参的构造函数.
它看起来好像左值被绑定到右值引用.一个滑稽的答案可能是左值转换为右值.但问题是,这是一个编译器错误,如果不是,那么神圣标准是如何允许的呢?
编辑:我设法将它全部减少到以下非常短的例子:
void foo( double&& ) {}
int main()
{
char ch = '!';
foo( ch );
}
Run Code Online (Sandbox Code Playgroud)
无法用MSVC 11.0编译,用MinGW 4.7.1编译,这是对的吗?
想必您同意这是有效的?
void foo( double ) {} // pass-by-value
int main()
{
char ch = '!';
foo( ch );
}
Run Code Online (Sandbox Code Playgroud)
有一个从charto 的隐式转换double,因此该函数是可行的。
在您编辑的问题的示例中也是如此,有一个隐式转换会生成一个临时值(即右值),并且右值引用参数绑定到该临时值。如果您愿意,可以显式进行该转换:
void foo( double&& ) {} // pass-by-reference
int main()
{
char ch = '!';
foo( double(ch) );
}
Run Code Online (Sandbox Code Playgroud)
但这并没有真正改变任何事情。double如果->char只能显式转换(例如,对于具有显式构造函数或显式转换运算符的类类型),但doubletochar是有效的隐式转换,则这是必要的。
您正在考虑的“右值引用不能绑定到左值”规则是指将 a 绑定T&&到T左值,并且该规则没有被破坏,因为double&&不绑定到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");
Run Code Online (Sandbox Code Playgroud)
根据当前规则,std::string通过隐式转换创建临时值,然后 std::vector<T>::push_back(T&&)调用临时值,并将临时值移动到向量中。如果该push_back重载对于转换结果不可行,则上面的代码将调用std::vector<T>::push_back(const T&),这将导致复制。当前的规则使这个现实世界的用例更加高效。如果规则规定 rvalue-refs 无法绑定到隐式转换的结果,则必须更改上面的代码才能获得移动的效率:
v.push_back( std::string{"text"} );
Run Code Online (Sandbox Code Playgroud)
恕我直言,std::string当构造函数不显式时,必须显式构造 a 是没有意义的。我希望显式/隐式构造函数具有一致的行为,并且我希望第一个push_back示例更加高效。
| 归档时间: |
|
| 查看次数: |
2442 次 |
| 最近记录: |