Comment écririez-vous une fonction de modèle qui prend un nombre de variable d'arguments de fonction non-POD homogènes en C ++ 11?
Supposons que nous voulions écrire une fonction min pour tout type qui définit le moins que " opérateur <"comme suit: p> Ce qui précède est illégal C ++ 11, comment écrivez-vous légalement? p> p>
4 Réponses :
C'est un peu compliqué mais c'est ce que vous obtenez si vous voulez
Arguments hétérogènes: La première version est beaucoup plus intéressante cependant. common_type code>
cherche le type que tous les arguments peuvent être contraints. C'est
nécessaire car une fonction avec des arguments hétérogènes revenant
L'un ou l'autre d'entre eux doit trouver ce type. Cependant, cela pourrait être
contourné en utilisant
boost :: variante code> mais pour les types intégrés, c'est
plutôt inutile car ils doivent être contraints pour être comparé quand même. p> p>
@Konradrudolph merci. Cela doit être résolu maintenant et les types de retour ainsi que les types d'arguments du foncteur doivent correspondre exactement aux types utilisés pour appeler min code> avec. Bien que je pense que cela gâche toujours des arguments mixtes de lvalue / rvalue, mais je ne sais pas comment résoudre ce problème. Quelque chose d'autre qui est toujours mal?
Je pense que dans ce cas, le meilleur recours est réellement de transmettre tous les arguments comme const Réf. Et si vous modifiez ou stockez les arguments, transmettez tout de valeur et espoir le meilleur.
@Konradrudolph mais qui empêcherait l'utilisation, telle que min (A, B) = 0 code> que je considérerais quelque peu utile.
Vrai mais même std :: min code> ne le permet pas.
@Konradrudolph Donc, ce que nous avons ici est un meilleur std :: min code> bien que à un certain coût.
homogène? (comme @ JESSE a noté, il s'agit de l'équivalent à std :: min dans la bibliothèque standard.) p> Si vous n'aimez pas les accolades supplémentaires, faites un modèle variadique qui transmet la mise en œuvre de la liste d'initialistes: P> std :: initializer_list code> strong>.
template <typename... T>
auto min(T&&... args) -> decltype(min_impl({std::forward<T>(args)...}))
{
return min_impl({std::forward<T>(args)...});
}
...
return min(8, 5, 1, 4, 6);
C'est aussi la même chose que std :: min ) (peut-être qu'il devrait être a souligné que c'est un type de pod ou non ne fait pas une différence).
Il convient de noter que cela ne fonctionnera pas pour les types de déplacement uniquement. Vous ne pouvez pas sortir d'un initialiszer_list code>.
Une autre possibilité:
template <typename T, typename... T2> T min(T x1, T2... rest); template <typename T> T min(T x) { return x; } template <typename T, typename... T2> T min(T x1, T2... rest) { return std::min (x1, min (rest...)); }
Premièrement, les modèles variadiques n'incluent pas un moyen de dire «un nombre variable d'arguments d'un seul type». Lorsque vous utilisez des modèles variadiques, vous obtenez un paquet de paramètres qui est un ensemble d'arguments zéro ou plus, chacun avec un type éventuellement unique: Bien que des modèles variadiques ne prennent pas en charge directement Ce que vous voulez, vous pouvez utiliser puis appliquer La mise en œuvre modifiée ci-dessus empêchera la fonction d'être utilisée à tout moment, les arguments ne sont pas tous exactement les mêmes selon Vous préférez probablement ne pas utiliser ces astuces si vous n'êtes pas obligé. Utiliser une initialisateur_List alors que KennyTM suggère est probablement une meilleure idée. En fait, si vous mettez vraiment en œuvre Min et max, vous pouvez vous épargner des problèmes car la bibliothèque standard comprend déjà des surcharges qui prennent une version initialisateur_list. P> car il y a une seule version d'argument de L'implémentation variadique de Nous savons donc que code> jeton A seulement a défini des significations pour ces packs de paramètres (et des fonctions Vararg, mais c'est à côté du point). Donc, vous ne pouvez pas l'utiliser avec des packs non paramètres: p>
activer_if code> et utiliser la règle "Sfinae" pour imposer cette contrainte. D'abord voici une version qui sans la contrainte: p>
activer_if code> Pour vous assurer que les types sont tous identiques. P> < Pré> xxx pré>
is_same code>. P>
Comment
est-ce document commun_type
min () code> la version variadique est sélectionnée uniquement quand il y a deux ou plusieurs paramètres. Cela signifie que
taille de ... (US) code> est au moins un. Dans le cas où il est exactement un,
common_type
is_same
min () code> appels
min (US ...) code>. Tant que cet appel ne fonctionne que lorsque tous les types dans
US ... CODE> sont les mêmes que nous savons que
commont_type
is_same
min (A, B) < / Code> ne fonctionne que si
A code> et
B code> est le même type. Et nous savons que
min (c, a, b) code> appels
min (a, b) code> donc
min (c, a, b) code> peut seulement être appelé si
A code> et
B code> est le même type et si
C code> est également le même type.
min (d, c, a, b) code> appels
min (c, a, b) code> nous savons que
min (d, c, a, b) code> ne peut être appelé que si
c code>,
A code> et
b code> sont tous identiques et en outre si
d < / code> est aussi le même type. C. P> p>
Si vous exécutez que tous les types sont les mêmes, quelle est l'utilisation de common_type code>? En outre,
common_type
US ... code> étant identique à
t code>.
@PMR Common_Type fait partie de la manière dont les types d'arguments sont forcés d'être les mêmes. Tous les types dans US ... CODE> seront les mêmes, de sorte que le type_TYPE sera ce type. Ceci est prouvé par induction.
@PMR J'ai ajouté un peu comment cette condition fonctionne pour que tous les types soient identiques.
Ce qui précède n'est pas illégal (en supposant que le
... code> s est juste une méthode pseudocode de dire "plus de choses ici").
@ R.martinhofernandes: je devine par le titre que ceux-ci ne sont pas pseudocode; L'OP a besoin d'arguments variables.