La spécification d'un type pour tous les arguments passés à variadic fonction ou variadic template fonction w/out à l'aide du tableau, vecteur, les structures, etc?
Je crée une fonction (éventuellement en fonction de membre de, pas que c'est important... peut-être que c'est?) qui doit accepter un nombre indéterminé d'arguments, mais je veux tous à être le même type. Je sais que je pourrais passer dans une matrice ou un vecteur, mais je veux être en mesure d'accepter la liste des arguments directement, sans structure supplémentaire ou même entre parenthèses supplémentaires. Il ne ressemble pas à variadic fonctions par eux-mêmes sont typesafe, et je ne savais pas vraiment comment aller à ce sujet w/variadic template fonctions. Voici en gros ce que je vise (plus que probablement pas le code est correct, et totalement non dans le but d'obtenir des listes de dragons, lol):
//typedef for dragon_list_t up here somewhere.
enum Maiden {
Eunice
, Beatrice
, Una_Brow
, Helga
, Aida
};
dragon_list_t make_dragon_list(Maiden...) {
//here be dragons
}
OU
template<Maiden... Maidens> dragon_list_t make_dragon_list(Maidens...) {
//here be dragons
}
UTILISATION
dragon_list_t dragons_to_slay
= make_dragon_list(Maiden.Eunice, Maiden.Helga, Maiden.Aida)
;
Essayé quelques choses de similaire à la déjà au-dessus, pas de dés. Des Suggestions? Évident oublis, j'ai peut être fait? Je sais que cela peut ne pas être une affaire énorme pour ce faire à la place:
dragon_list_t make_dragon_list(std::array<Maiden> maidens) {
//here be dragons.
}
dragon_list_t dragons_to_slay
= make_dragon_list({Maiden.Eunice, Maiden.Helga, Maiden.Aida})
;
mais je préfère être en mesure de faire la première manière, si possible.
Vous devez vous connecter pour publier un commentaire.
Que vous pouvez accepter les arguments avancés par les variadic template et laissez-le typage vérifier la validité plus tard, lorsqu'ils sont convertis.
Vous pouvez vérifier la convertibilité sur la fonction de l'interface de niveau, mais de rendre l'utilisation de la résolution de surcharge pour les rejeter d'emblée mauvais arguments par exemple, en utilisant SFINAE
Pour votre cas d'utilisation si vous connaissez les étapes pour passer d'un
std::array<>
à votredragon_list_t
, alors vous avez déjà résolu bien que, selon la première option ci-dessus ("convertir plus tard"):Si vous combinez cela avec le ci-dessus
is_convertible
approche que vous avez un rejet précoce modèle qui fait aussi de la résolution de surcharge sur les arguments et les rejette si non applicable.ToType
(Dragon
), pas des arguments les uns des autres. Donc D1->B est vérifiée et D2->B aussi, mais D1->D2 n'est pas cochée.Si vous n'utilisez pas
template
sur le paramètre qui n'est pas dans le pack de la variadic fonction permettra de résoudre à avoir tous les arguments du même type.Voici un exemple pour une longue
max
fonction qui n'accepteint
s (ou types convertiblesint
).Explication: Lorsque vous déballez l'argument pack (
args...
) le compilateur recherche pour le meilleur de la surcharge. Si le pack a qu'un seul paramètre, alors le meilleur candidat estmaximum(int)
de sorte que le seul paramètre doit être de typeint
(ou convertibles àint
). Si il y a plusieurs éléments dans le pack alors le seul candidat estmaximum(int, typename...)
donc le premier argument doit être de typeint
(ou convertibles àint
). Il est simple de prouver par induction que tous les types dans le pack doit être d'un type convertibleint
).Depuis que vous avez inclus le C++0x balise, la réponse la plus évidente serait de rechercher initialiseur de listes. Un initialiseur liste vous permet de spécifier un certain nombre d'arguments de la ctor qui sera automatiquement convertie en une seule structure de données pour le traitement par le ctor.
Leur principal (exclusif?) l'utilisation est exactement le genre de situation que vous avez mentionné, en passant, un certain nombre d'arguments du même type à utiliser dans la création d'une sorte de liste/tableau/la collecte des autres objets. Il va être pris en charge par (pour un exemple)
std::vector
, de sorte que vous pouvez utiliser quelque chose comme:de créer un vecteur de trois
dragon
objets. La plupart (tous?) de l'autre, les collections comprennent la même chose, donc si vous avez vraiment insister sur une liste de dragons vous devriez être en mesure d'obtenir ce assez facilement ainsi.J'ai récemment eu besoin de contraindre un paramètre pack à un seul type, ou au moins convertibles à ce type. J'ai fini par trouver une autre façon:
La chose que j'ai aimé à propos de cette solution est que je peux appliquer
check_all
à d'autres traits trop.Bien que la question est étiqueté C++11, je pense que C++17 + des concepts de solution serait intéressant d'ajouter, vu qu'il est désormais en charge du CCAG, et d'autres vont bientôt suivre.
d'abord définir un concept simple
puis il suffit d'utiliser variadic template parameters
Beaucoup plus facile avec l'avènement des concepts!
Ça dépend vraiment de ce que vous essayez de mettre en œuvre, exactement.
Généralement
enum
indique exécution des sous-types d'une classe particulière, ou une victime de l'union (boost::variant). Mais dans ce cas, vous souhaitez passer laenum
directement. En outre, vous disposez d'un ensemble limité de valeurs possibles, et chaque appel de fonction, forme un sous-ensemble. Vraiment ce que vous représentez, c'est un sous-ensemble, et non pas plusieurs paramètres à tous.Le meilleur moyen de représenter un sous-ensemble d'un ensemble fini est un bitset. De grands ensembles devraient utiliser
std::bitset
; petits jeux pouvez simplement utiliserunsigned long
.ou, puisque vous avez l'air de vouloir gérer les variations au moment de la compilation,
Il devrait être possible de générer des puissances de 2 automatiquement à l'aide d'un
operator+
surchargé sur leenum
type. Mais je ne suis pas sûr que je suis sur la bonne voie.enum { first_value = 1, second_value = 1 << 1, third_value = 1 << 2 };
Je voudrais essayer de garder les choses simples, et la solution la plus simple je pense est de simplement en utilisant un simple vieux vecteur. À l'aide de C++0x fonctionnalités que vous pouvez obtenir une syntaxe qui est semblable (même si pas exactement) ce que vous voulez:
En bref, vous devriez probablement juste de créer un vecteur. Il n'est pas beaucoup au-dessus, surtout si vous utilisez quelque chose comme boost::list_of ou C++0x l'initialiseur de liste. La sémantique des frais généraux est minime, et il est plus souple (vous pouvez passer de la liste avec un nombre d'arguments connue qu'à l'exécution).
Si tu le voulais vraiment, vous pouvez utiliser variadic template parameters pour ce faire:
C'est typesafe, et extensible (vous pouvez faire ce prendre d'autres choses que de dragons, si vous en avez envie).
Je pense que le code suivant est utile pour votre cas:
Une proposition récente, Homogène variadic fonctions, les adresses en faisant quelque chose comme votre première construction juridique. Sauf, bien sûr, utiliser le paramètre pack vous permettra d'avoir un nom. Aussi la syntaxe exacte n'a pas l'air très encore en béton.
Donc, en vertu de la proposition, ce sera effectivement juridique (vous pouvez voir une semblable construction dans le paragraphe "Le modèle d'introduction" dans le document):