2015-08-04 6 views
1

Существует требование, когда мне нужно передать 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. Но когда есть множество аргументов, у него есть проблемы.

ответ

2

Чтобы сохранить RValue-Несс, вы должны move или forward параметр (ы)

template<typename... intrgs> 
void Second (intrgs&&... args) { 
    Third(std::forward<intrgs>(args)...); 
} 
+0

'move' бы бросить их безоговорочно rvalues , что не «сохраняет» rvalue-ness. – Barry

+0

@Barry, можете ли вы или Бо оценить больше о том, почему 'std :: forward' должен быть предпочтительнее' std :: move'? – iammilind

+0

@iammilind - 'std :: move' всегда будет делать параметр rvalue, даже если он не был первоначально. 'std :: forward' сохранит способ передачи параметров (как говорит Барри). Если вы всегда * передаете rvalue на 'Second', это не имеет значения. –

4

Вы должны использовать std::forward:

template<typename... intrgs> 
void Second (intrgs&&... args) { 
    Third(std::forward<intrgs>(args)...); 
} 
+0

Можете ли вы рассказать больше о том, почему 'std :: move' не будет хорошей идеей? – iammilind

Смежные вопросы