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