Существует требование, когда мне нужно передать rvalue из 1 функции в другую функцию с помощью вариационного шаблона. Для того, чтобы избежать реальной сложности кода, минимальный пример ниже с помощью int
:Ошибка компилятора при передаче ссылки rvalue через вариативные шаблоны
void Third (int&& a)
{}
template<typename... Args>
void Second (Args&&... args) {
Third(args...);
}
void First (int&& a) {
Second(std::move(a)); // error: cannot bind ‘int’ lvalue to ‘int&&’
Third(std::move(a)); // OK
}
int main() {
First(0);
}
First(0)
называется правильно. Если я вызываю Third(int&&)
непосредственно, он работает нормально, используя std::move()
. Но вызов Second(Args&&...)
results in:
error: cannot bind ‘int’ lvalue to ‘int&&’
Third(args...); ^
note: initializing argument 1 of ‘void Third(int&&)’
void Third (int&& a)
Что такое правильный способ для достижения успешной компиляции для Second(Args&&...)
?
FYI: В реальном коде Second(Args&&...)
представляет собой смесь значений lvalues, rvalues и rvalue. Следовательно, если я использую:
Third(std::move(args...));
it works. Но когда есть множество аргументов, у него есть проблемы.
'move' бы бросить их безоговорочно rvalues , что не «сохраняет» rvalue-ness. – Barry
@Barry, можете ли вы или Бо оценить больше о том, почему 'std :: forward' должен быть предпочтительнее' std :: move'? – iammilind
@iammilind - 'std :: move' всегда будет делать параметр rvalue, даже если он не был первоначально. 'std :: forward' сохранит способ передачи параметров (как говорит Барри). Если вы всегда * передаете rvalue на 'Second', это не имеет значения. –