问题
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
回答1:
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)
MSVC online tester
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.
来源:https://stackoverflow.com/questions/26480413/how-to-copy-from-primitive-type-variables-when-passing-through-rvalue-reference