Страницы

Поиск по вопросам

воскресенье, 5 января 2020 г.

В чём смысл std::forward при передаче параметров?

#cpp #шаблоны_с++ #ссылки #параметры


В чём разница между следующими двумя способами передачи параметров?

template  smth(Args &&...args) : base(args...) {}




template  smth(Args &&...args) : base(std::forward(args)...) {}

    


Ответы

Ответ 1



Предположим, что конструктор base принимает move-only параметр по значению: struct base { base(std::unique_ptr value); }; В таком случае первый вариант не скомпилируется: template smth(Args &&...args) : base(args...) {} попытка сделать копию ^^^^ Тут можно написать std::move и это будет работать: template smth(Args &&...args) : base(std::move(args)...) {} Однако в случае если у base два конструктора, один из которых перемещает значение, а другой принимает ссылку: struct base { base(std::unique_ptr&& value); base(std::unique_ptr& value); }; И если мы хотим чтобы smth передавал в base именно те типы аргументов, с которыми его вызвали, то std::move нам не подойдет - он всегда будет превращать аргумент в r-value ссылку. Для этого есть std::forward, который сохраняет оригинальный тип аргумента: struct smth : base { template smth(Args &&...args) : base(std::forward(args)...) {} }; std::unique_ptr p; smth s1(p); // OK, будет вызван base(std::unique_ptr&); smth s2(st::move(p)); // OK, будет вызван base(std::unique_ptr&&); Примечание: std::forward(t) работает только с "универсальнами ссылками", т.е. когда T - это параметр шаблона функции (конструктора), а t - аргумент этой функции с типом T&& (это специальное исключение в языке, такой тип T&& не является r-value ссылкой, а заставляет T повторять тип того, что передали в функцию).

Комментариев нет:

Отправить комментарий