C++
Perfect Forwarding
Поиск…
замечания
Для идеальной пересылки требуется пересылка ссылок , чтобы сохранить ref-квалификаторы аргументов. Такие ссылки появляются только в выведенном контексте . То есть:
template<class T>
void f(T&& x) // x is a forwarding reference, because T is deduced from a call to f()
{
g(std::forward<T>(x)); // g() will receive an lvalue or an rvalue, depending on x
}
Следующее не связано с совершенной пересылкой, потому что T
не выводится из вызова конструктора:
template<class T>
struct a
{
a(T&& x); // x is a rvalue reference, not a forwarding reference
};
C ++ 17 позволит вычесть аргументы шаблона класса. Конструктор «a» в приведенном выше примере станет пользователем ссылки пересылки
a example1(1);
// same as a<int> example1(1);
int x = 1;
a example2(x);
// same as a<int&> example2(x);
Заводские функции
Предположим, мы хотим написать фабричную функцию, которая принимает произвольный список аргументов и передает эти аргументы без изменений в другую функцию. Примером такой функции является make_unique
, которая используется для безопасного создания нового экземпляра T
и возврата unique_ptr<T>
которому принадлежит экземпляр.
Языковые правила, касающиеся вариационных шаблонов и ссылок на rvalue, позволяют нам написать такую функцию.
template<class T, class... A>
unique_ptr<T> make_unique(A&&... args)
{
return unique_ptr<T>(new T(std::forward<A>(args)...));
}
Использование эллипсов ...
указывает пакет параметров, который представляет собой произвольное количество типов. Компилятор расширит этот пакет параметров до правильного количества аргументов на сайте вызова. Эти аргументы затем передаются в конструктор T
, используя std::forward
. Эта функция необходима для сохранения ref-квалификаторов аргументов.
struct foo
{
foo() {}
foo(const foo&) {} // copy constructor
foo(foo&&) {} // copy constructor
foo(int, int, int) {}
};
foo f;
auto p1 = make_unique<foo>(f); // calls foo::foo(const foo&)
auto p2 = make_unique<foo>(std::move(f)); // calls foo::foo(foo&&)
auto p3 = make_unique<foo>(1, 2, 3);