La norme C ++ 17 introduit des "guides de déduction de modèles". Je suppose qu'ils ont quelque chose à voir avec la nouvelle déduction d'arguments de modèle pour les constructeurs introduite dans cette version de la norme, mais je n'ai pas encore vu une explication simple, de style FAQ, de ce qu'ils sont et à quoi ils servent.
Que sont les guides de déduction de modèles dans C ++ 17?
Pourquoi (et quand) en avons-nous besoin?
Comment les déclarer?
Réponses:
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 êtretypename std::iterator_traits<Iterator>::value_type
. Mais comment dire au compilateur sans avoir à tapervector<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 lavector
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'uninitializer_list
utilise explicitement lesvector
'sT
, 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"}; //thing.t is a `std::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.
la source
vector v{first, last};
je ne ferais pas la bonne chose :(std::string{32,'*'}[0] == ' '
(pour ASCII). Mais tout cela est vrai depuis C ++ 11.