Я могу скопировать из переменной не примитивного типа с помощью конструктора копирования и передать ее через аргумент ссылочной функции rvalue.
Но как это сделать с переменными примитивного типа?
например:
#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;
}
Результат в Visual Studio 2013 — «01» с ошибкой подтверждения.
Ваш код верен, и это похоже на ошибку в VS2013.
Проще 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 );
}
Выход должен быть:
f(rv)
f(rv)
Обратите внимание, что дальнейшее тестирование показывает, что ошибка действительно (int)x2
MSVC считается lvalue; Это не ошибка в расширении MSVC, которое позволяет привязывать rvalues к ссылкам lvalue (так как ссылка на rvalue в любом случае лучше соответствует).
Вы можете исправить это, используя /Za
переключатель.
Выражение int(x2)
покрывается C ++ 14 [expr.type.conv] / 2 (C ++ 11 имеет такую же нумерацию):
спецификатор простого типа (7.1.6.2) или же спецификатор typename (14.6) с последующим в скобках список_выражений создает значение указанного типа с учетом списка выражений. Если список выражений является одним выражением, выражение преобразования типа эквивалентно (в определенности и если определено в значении) соответствующему приведенному выражению (5.4).
Соответствующее приведенное выражение:
Результат выражения (T) cast-expression имеет тип T. Результатом является lvalue, если T является ссылочным типом lvalue или ссылкой rvalue на тип функции, и xvalue, если T является ссылкой rvalue на тип объекта; в противном случае результат является prvalue.