En C ++ 11, il existe des modèles variadiques comme celui-ci:
template< class T, class... Args >
unique_ptr<T> make_unique( Args&&... args )
{
return unique_ptr<T>(new T(std::forward<Args>(args)...));
}
Il y a quelques curiosités à ce sujet: L'expression std::forward<Args>(args)...
utilise les deux Args
et args
un seul ...
jeton. De plus, std::forward
une fonction de modèle non variadique ne prend qu'un seul paramètre de modèle et un argument. Quelles sont les règles de syntaxe pour cela (en gros)? Comment peut-il être généralisé?
Aussi: Dans l'implémentation de la fonction, les points de suspension ( ...
) se trouvent à la fin de l'expression d'intérêt. Y a-t-il une raison pour laquelle, dans la liste des arguments de modèle et la liste des paramètres, les points de suspension sont au milieu?
c++
c++11
variadic-templates
Ralph Tandetzky
la source
la source
...
vient avant que l'identifiant soit introduit. Lors de l'utilisation de l'un ou des deux types de packs, le...
se trouve après le modèle d'expression à développer.Réponses:
Dans le contexte du modèle variadique, les points de suspension
...
sont utilisés pour décompresser le pack de paramètres du modèle s'il apparaît sur le côté droit d'une expression (appelez ce modèle d' expression pendant un moment). La règle est que tout motif se trouvant sur le côté gauche de...
est répété - les motifs décompressés (appelez-les maintenant expressions ) sont séparés par des virgules,
.Il peut être mieux compris par quelques exemples. Supposons que vous ayez ce modèle de fonction:
Maintenant, si j'appelle cette fonction en passant
T
comme{int, char, short}
, alors chacun des appels de fonction est développé comme:Dans le code que vous avez publié,
std::forward
suit le quatrième modèle illustré parn()
l'appel de fonction.Notez la différence entre
x(args)...
ety(args...)
au - dessus!Vous pouvez également utiliser
...
pour initialiser un tableau comme:qui est étendu à ceci:
Je viens de réaliser qu'un modèle pourrait même inclure un spécificateur d'accès tel que
public
, comme indiqué dans l'exemple suivant:Dans cet exemple, le modèle est développé comme:
Autrement dit,
mixture
dérive publiquement de toutes les classes de base.J'espère que cela pourra aider.
la source
x+args...
devrait être étendu àx+arg0,x+arg1,x+arg2
, nonx+arg0,arg1,arg2
....
s'applique à chaque entité extensible dans le modèle.x+args...
devrait s'étendre àx+arg0,x+arg1,x+arg2
, nonx+arg0,arg1,arg2
.sizeof...(T)
n'est pas nécessaire là-bas. Vous pouvez simplement écrire:int a[] = { ___ };
Ce qui suit est tiré de la conférence «Les modèles variadiques sont Funadic» par Andrei Alexandrescu à GoingNative 2012. Je peux le recommander pour une bonne introduction sur les modèles variadiques.
Il y a deux choses que l'on peut faire avec un pack variadic. Il est possible de postuler
sizeof...(vs)
pour obtenir le nombre d'éléments et l'élargir.Règles d'extension
L'expansion se poursuit vers l'intérieur vers l'extérieur. Lorsque vous développez deux listes en mode verrouillé, elles doivent avoir la même taille.
Plus d'exemples:
Développe tout
Ts
dans la liste d'arguments du modèle deA
, puis la fonctionhun
se développe avec toutvs
.Développe tout
Ts
dans la liste d'arguments du modèle deA
et allvs
comme arguments de fonction pourhun
.Étend la fonction
hun
avecTs
etvs
en lock-step.Remarque:
Ts
n'est pas un type etvs
n'est pas une valeur! Ce sont des alias pour une liste de types / valeurs. Les deux listes peuvent être potentiellement vides. Les deux n'obéissent qu'à des actions spécifiques. Donc ce qui suit n'est pas possible:Loci d'expansion
Arguments de fonction
Listes d'initialisation
Spécificateurs de base
Listes d'initialisation des membres
Listes d'arguments Tempate
Ne compilera que s'il y a une correspondance possible pour les arguments.
Capturer des listes
Listes d'attributs
C'est dans la spécification, mais il n'y a pas encore d'attribut qui puisse être exprimé comme un type.
la source