C++
Inoltro perfetto
Ricerca…
Osservazioni
L'inoltro perfetto richiede l' inoltro dei riferimenti per preservare i qualificatori di riferimento degli argomenti. Tali riferimenti appaiono solo in un contesto dedotto . Questo è:
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
}
Quanto segue non implica un inoltro perfetto, perché T
non è dedotto dalla chiamata del costruttore:
template<class T>
struct a
{
a(T&& x); // x is a rvalue reference, not a forwarding reference
};
C ++ 17 consentirà la deduzione degli argomenti del modello di classe. Il costruttore di "a" nell'esempio precedente diventerà un utente di un riferimento di inoltro
a example1(1);
// same as a<int> example1(1);
int x = 1;
a example2(x);
// same as a<int&> example2(x);
Funzioni di fabbrica
Supponiamo di voler scrivere una funzione factory che accetta un elenco arbitrario di argomenti e passa quegli argomenti non modificati ad un'altra funzione. Un esempio di tale funzione è make_unique
, che viene utilizzato per costruire in modo sicuro una nuova istanza di T
e restituire un unique_ptr<T>
che possiede l'istanza.
Le regole linguistiche relative ai modelli variadici e ai riferimenti rvalue ci consentono di scrivere una funzione del genere.
template<class T, class... A>
unique_ptr<T> make_unique(A&&... args)
{
return unique_ptr<T>(new T(std::forward<A>(args)...));
}
L'uso di ellissi ...
indica un pacchetto di parametri, che rappresenta un numero arbitrario di tipi. Il compilatore espande questo pacchetto di parametri al numero corretto di argomenti nel sito di chiamata. Questi argomenti vengono quindi passati al costruttore di T
usando std::forward
. Questa funzione è necessaria per conservare i qualificatori di ref degli argomenti.
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);