Les guides de déduction de modèle sont des modèles associés à une classe de modèle qui indiquent au compilateur comment traduire un ensemble d'arguments de constructeur (et leurs types) en paramètres de modèle pour la classe.
L'exemple le plus simple est celui de std::vector
et son constructeur qui prend une paire d'itérateurs.
template<typename Iterator>
void func(Iterator first, Iterator last)
{
vector v(first, last);
}
Le compilateur a besoin de comprendre ce que vector<T>
de » T
type sera. Nous savons quelle est la réponse; T
devrait être typename std::iterator_traits<Iterator>::value_type
. Mais comment dire au compilateur sans avoir à taper vector<typename std::iterator_traits<Iterator>::value_type>
?
Vous utilisez un guide de déduction:
template<typename Iterator> vector(Iterator b, Iterator e) ->
vector<typename std::iterator_traits<Iterator>::value_type>;
Cela indique au compilateur que, lorsque vous appelez un vector
constructeur correspondant à ce modèle, il déduit la vector
spécialisation en utilisant le code à droite de ->
.
Vous avez besoin de guides lorsque la déduction du type des arguments n'est pas basée sur le type de l'un de ces arguments. L'initialisation d'un à vector
partir d'un initializer_list
utilise explicitement les vector
's T
, donc il n'a pas besoin d'un guide.
Le côté gauche ne spécifie pas nécessairement un constructeur réel. La façon dont cela fonctionne est que, si vous utilisez la déduction de constructeur de modèle sur un type, cela correspond aux arguments que vous passez à tous les guides de déduction (les constructeurs réels du modèle principal fournissent des guides implicites). S'il existe une correspondance, il l'utilise pour déterminer les arguments de modèle à fournir au type.
Mais une fois que cette déduction est faite, une fois que le compilateur a déterminé les paramètres du modèle pour le type, l'initialisation de l'objet de ce type se déroule comme si rien de tout cela ne s'était produit. Autrement dit, le guide de déduction sélectionné ne doit pas nécessairement correspondre au constructeur sélectionné.
Cela signifie également que vous pouvez utiliser des guides avec des agrégats et une initialisation d'agrégats:
template<typename T>
struct Thingy
{
T t;
};
Thingy(const char *) -> Thingy<std::string>;
Thingy thing{"A String"};
Les guides de déduction ne sont donc utilisés que pour déterminer le type en cours d'initialisation. Le processus réel d'initialisation fonctionne exactement comme avant, une fois que cette détermination a été faite.