#cpp #шаблоны_с++ #ссылки #параметры
В чём разница между следующими двумя способами передачи параметров? templatesmth(Args &&...args) : base(args...) {} template smth(Args &&...args) : base(std::forward (args)...) {}
Ответы
Ответ 1
Предположим, что конструктор base принимает move-only параметр по значению: struct base { base(std::unique_ptrvalue); }; В таком случае первый вариант не скомпилируется: 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 повторять тип того, что передали в функцию).
Комментариев нет:
Отправить комментарий