Cosa sono le guide alla detrazione del modello e quando dovremmo usarle?


87

Lo standard C ++ 17 introduce "guide alla detrazione dei modelli". Immagino che abbiano qualcosa a che fare con la nuova deduzione dell'argomento del modello per i costruttori introdotta in questa versione dello standard, ma non ho ancora visto una semplice spiegazione in stile FAQ di cosa sono ea cosa servono.

  • Cosa sono le guide alla detrazione dei modelli in C ++ 17?

  • Perché (e quando) ne abbiamo bisogno?

  • Come li dichiaro?



In particolare, sarei interessato a sapere se eventuali guide alla deduzione sono effettivamente fornite dal C ++ 17 STL (ad esempio per std :: pair o std :: tuple). Qual è l'elenco completo dei tipi di modelli standard "deducibili" a partire da C ++ 17?
Quuxplusone


Sarei interessato a sapere se qualche compilatore lo supporta. Ho provato gcc, clang e vc ++. rextester.com/DHPHC32332 Nevermind, ho scoperto che funziona solo con gc ++ 8.1 C ++ 17 e 2a g ++ -std = c ++ 17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
Jean-Simon Brochu

Risposte:


98

Le guide alla deduzione del modello sono modelli associati a una classe modello che indicano al compilatore come tradurre un insieme di argomenti del costruttore (e i loro tipi) in parametri del modello per la classe.

L'esempio più semplice è quello di std::vectore il suo costruttore che accetta una coppia di iteratori.

template<typename Iterator>
void func(Iterator first, Iterator last)
{
  vector v(first, last);
}

Il compilatore ha bisogno di capire che cosa vector<T>'s Ttipo sarà. Sappiamo qual è la risposta; Tdovrebbe essere typename std::iterator_traits<Iterator>::value_type. Ma come facciamo a dirlo al compilatore senza dover digitare vector<typename std::iterator_traits<Iterator>::value_type>?

Utilizzi una guida alle detrazioni:

template<typename Iterator> vector(Iterator b, Iterator e) -> 
    vector<typename std::iterator_traits<Iterator>::value_type>;

Questo dice al compilatore che, quando chiami un vectorcostruttore che corrisponde a quel modello, dedurrà la vectorspecializzazione usando il codice a destra di ->.

Hai bisogno di guide quando la deduzione del tipo dagli argomenti non è basata sul tipo di uno di quegli argomenti. L'inizializzazione di un vectorda un initializer_listutilizza esplicitamente vector's T, quindi non ha bisogno di una guida.

Il lato sinistro non specifica necessariamente un costruttore effettivo. Il modo in cui funziona è che, se si utilizza la deduzione del costruttore del modello su un tipo, corrisponde agli argomenti passati rispetto a tutte le guide alla detrazione (i costruttori effettivi del modello principale forniscono guide implicite). Se c'è una corrispondenza, la usa per determinare quali argomenti del modello fornire al tipo.

Ma una volta che la deduzione è stata eseguita, una volta che il compilatore ha individuato i parametri del modello per il tipo, l'inizializzazione dell'oggetto di quel tipo procede come se nulla di tutto ciò accadesse. Cioè, la guida alla detrazione selezionata non deve necessariamente corrispondere al costruttore selezionato.

Ciò significa anche che puoi utilizzare le guide con aggregati e inizializzazione di aggregati:

template<typename T>
struct Thingy
{
  T t;
};

Thingy(const char *) -> Thingy<std::string>;

Thingy thing{"A String"}; //thing.t is a `std::string`.

Quindi le guide alle detrazioni vengono utilizzate solo per capire il tipo da inizializzare. Il processo effettivo di inizializzazione funziona esattamente come prima, una volta effettuata tale determinazione.


7
Hmm, mi è appena venuto in mente che anche con la guida, vector v{first, last};non farà la cosa giusta :(
TC

3
@TC ... a meno che la cosa giusta non sia creare un vettore di iteratori. E std::string{32,'*'}[0] == ' '(per ASCII). Ma questo è stato tutto vero da C ++ 11.
Arne Vogel

2
cosa succede con il parametro vettore allocatore? cosa succederebbe se il parametro del vettore allocatore non avesse un argomento predefinito? (non è possibile dedurlo da InputIterator)
gnzlbg

@NicolBolas: ti dispiacerebbe spiegare i dettagli di come le guide di deduzione implicite ed esplicite possono funzionare nel contesto di classi parzialmente o completamente specializzate (i cui costruttori chiaramente non devono avere tipi di parametri corrispondenti a quelli del modello principale)? È difficile trovare informazioni su questo tramite una rapida ricerca.
user541686

1
@NicolBolas: capisco. Non mi è chiaro se la domanda riguardi le guide alla deduzione esplicita ... Penso che sia utile se includi solo ciò che hai letteralmente scritto in questo commento.
user541686
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.