Не работает std::forward
Нужно, что бы в зависимости от того, какая вызывается перегрузка push_back (lvalue или rvalue), вызывался соответствующий конструктор (копирования или перемещения):
struct tmpS {
tmpS() {}
tmpS(const tmpS& s) {
std::cout << "copy\n";
}
tmpS(tmpS&& s) {
std::cout << "move\n";
}
};
template<typename Type>
void pass_to_construct(Type&& arg) { // универсальная ссылка
tmpS t = std::forward<Type>(arg);
}
template<typename T>
struct v {
v() {}
void push_back(T&& value) { // вызовется эта перегрузка
pass_to_construct(value);
}
void push_back(const T& value) {
pass_to_construct(value);
}
};
int main()
{
v<tmpS> s;
s.push_back(tmpS()); // rvalue
}
Код выше вызывает конструктор копирования (печатает copy). Почему не перемещения?
Ответы (1 шт):
Попробуйте так:
template<typename T>
struct v {
v() {}
void push_back(T&& value) { // вызовется эта перегрузка
pass_to_construct(std::forward<T&&>(value));
}
void push_back(T& value) { // вызовется эта перегрузка
pass_to_construct(value);
}
};
Без этого в pass_to_construct всегда передается lvalue, каковым является аргумент функции.
Вот рабочий код: https://ideone.com/P4jR4w
Еще вариант -
void push_back(T&& value) { // вызовется эта перегрузка
pass_to_construct(std::move(value));
}
void push_back(T& value) { // вызовется эта перегрузка
pass_to_construct(value);
}
Какой вариант более правильный - не уверен... Ощущение, что в данном случае они оба сработают.
[P.S. По некотором раздумии - в данном случае нет универсальной ссылки, так что лучше применять move.]
Но в том, что в pass_to_construct в вашем варианте вы в обоих случаях передавали аргумент вызывающей функции, т.е. lvalue - это несомненно...
"По-моему, так"... (с) Пух