如何在传递右值引用函数参数时从原始类型变量中复制 [英] How to copy from primitive type variables when passing through rvalue reference function arguments
问题描述
我可以通过复制构造函数从非原始类型变量中复制,并将其传递通过右值引用函数参数。
但是如何使用原始类型变量?
例如:
#include< cassert>
#include< iostream>
struct MyClass
{
int m = 0;
};
MyClass& f(MyClass& x)
{
x.m ++;
return x;
}
inline MyClass f(MyClass&& x)
{
return f(x);
}
int& f(int& x)
{
x ++;
return x;
}
inline int f(int& x)
{
return f(x);
}
int main()
{
MyClass x1;
auto y1 = f(MyClass(x1)); //调用f(MyClass&&)
//结果:x1.m = 0,y1.m = 1
int x2 = 0;
auto y2 = f(int(x2)); //调用f(int&)
//结果:x2 = 1,y2 = 1
std :: cout< x1.m < x2; // Result in VS2013:'01'but'00'in gcc and clang!
assert(x1.m == x2); //失败在VS2013!
return 0;
}
Visual Studio 2013中的结果为01,断言失败。 p>
http://rextester.com/CAPY87169
您的代码是正确的,这似乎是VS2013中的一个错误。
更简单的MCVE:
#include< iostream>
void f(int& x){std :: cout< f(lv)\\\
; }
void f(int&& x){std :: cout<< f(rv)\\\
; }
int main()
{
int x2 = 0;
f(int(x2));
f((int)x2);
}
输出应为:
f(rv)
f(rv)
请注意,进一步的测试显示该错误真的是MSVC将(int)x2
视为一个左值;它不是MSVC的扩展的错误,允许右值绑定到左值引用(因为右值引用是一个更好的匹配)。
您可以通过使用 / Za
开关。
表达式 int(x2)
由C ++ 14 [expr.type.conv] / 2(C ++ 11具有相同的编号)覆盖:
一个简单类型说明符(7.1.6.2)或 typename-specifier(14.6)后跟括号 expression-list 构造给定表达式列表的指定类型的值。如果表达式列表是单个表达式,则类型转换表达式与相应的强制转换表达式(5.4)是等效的(在定义中,如果定义的话)。
对应的转换表达式为:
表达式(T)cast-expression的结果是类型T.如果T是一个左值引用类型或一个右值引用的函数类型和一个xvalue如果T是对象类型的右值引用,结果是一个左值; 否则结果为prvalue 。
I can copy from a non-primitive type variable by copy constructor and pass it through rvalue reference function argument.
But how can do this with primitive type variables?
for example:
#include <cassert>
#include <iostream>
struct MyClass
{
int m = 0;
};
MyClass& f(MyClass& x)
{
x.m++;
return x;
}
inline MyClass f(MyClass&& x)
{
return f(x);
}
int& f(int& x)
{
x++;
return x;
}
inline int f(int&& x)
{
return f(x);
}
int main()
{
MyClass x1;
auto y1 = f(MyClass(x1)); // Calls f(MyClass&&)
// Result: x1.m = 0, y1.m = 1
int x2 = 0;
auto y2 = f(int(x2)); // Calls f(int&)
// Result: x2 = 1, y2 = 1
std::cout << x1.m << x2; // Result in VS2013: '01' But '00' in gcc and clang!
assert(x1.m == x2); // FAILED in VS2013!!!
return 0;
}
The result in Visual Studio 2013 is '01' with assertion failed.
http://rextester.com/CAPY87169
Your code is correct and this seems to be a bug in VS2013.
Simpler MCVE:
#include <iostream>
void f(int& x) { std::cout << "f(lv)\n"; }
void f(int&& x) { std::cout << "f(rv)\n"; }
int main()
{
int x2 = 0;
f( int(x2) );
f( (int)x2 );
}
Output should be:
f(rv)
f(rv)
Note that further testing shows that the bug is really that (int)x2
is treated as an lvalue by MSVC; it's not a bug with MSVC's extension to allow rvalues to bind to lvalue references (since the rvalue reference is a better match anyway).
You may be able to fix this by using the /Za
switch.
The expression int(x2)
is covered by C++14 [expr.type.conv]/2 (C++11 has the same numbering):
A simple-type-specifier (7.1.6.2) or typename-specifier (14.6) followed by a parenthesized expression-list constructs a value of the specified type given the expression list. If the expression list is a single expression, the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression (5.4).
The corresponding cast expression is:
The result of the expression (T) cast-expression is of type T. The result is an lvalue if T is an lvalue reference type or an rvalue reference to function type and an xvalue if T is an rvalue reference to object type; otherwise the result is a prvalue.
这篇关于如何在传递右值引用函数参数时从原始类型变量中复制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!