(Remarque: tuple
et tie
peut être extrait de Boost ou C ++ 11.)
Lors de l'écriture de petites structures avec seulement deux éléments, j'ai parfois tendance à choisir a std::pair
, car toutes les choses importantes sont déjà faites pour ce type de données, comme operator<
pour l'ordre strict-faible .
Les inconvénients sont cependant les noms de variables à peu près inutiles. Même si je l'ai moi-même créé typedef
, je ne me souviendrai pas 2 jours plus tard de ce first
que second
c'était et de ce que c'était exactement, surtout s'ils sont tous les deux du même type. Cela devient encore pire pour plus de deux membres, car la nidification pair
est vraiment nul.
L'autre option pour cela est untuple
, que ce soit à partir de Boost ou de C ++ 11, mais cela n'a pas vraiment l'air plus beau et plus clair. Je reviens donc à l'écriture des structures moi-même, y compris les opérateurs de comparaison nécessaires.
Puisque surtout cela operator<
peut être assez encombrant, j'ai pensé à contourner tout ce gâchis en me basant simplement sur les opérations définies pour tuple
:
Exemple de operator<
, par exemple pour un ordre strict-faible:
bool operator<(MyStruct const& lhs, MyStruct const& rhs){
return std::tie(lhs.one_member, lhs.another, lhs.yet_more) <
std::tie(rhs.one_member, rhs.another, rhs.yet_more);
}
( tie
fait tuple
des T&
références à partir des arguments passés.)
Edit : La suggestion de @DeadMG d'hériter en privé tuple
n'est pas mauvaise, mais elle présente de nombreux inconvénients:
- Si les opérateurs sont autonomes (éventuellement amis), je dois hériter publiquement
- Avec le casting, mes fonctions / opérateurs (en
operator=
particulier) peuvent être facilement contournés - Avec la
tie
solution, je peux laisser de côté certains membres s'ils ne comptent pas pour la commande
Y a-t-il des inconvénients dans cette implémentation que je dois prendre en compte?
tie
ne peut pas être appliqué aux membres de champ de bits.tie(...)
appels doivent être dupliqués dans divers opérateurs (=, ==, <, etc.), vous pouvez écrire une méthode en ligne privéemake_tuple(...)
pour encapsuler cela, puis l'appeler à partir de divers autres endroits, comme dansreturn lhs.make_tuple() < rhs.make_tuple();
(bien que le type de retour de cette méthode pourrait être amusante à déclarer!)auto tied() const{ return std::tie(the, members, here); }
Réponses:
Cela rendra certainement plus facile d'écrire un opérateur correct que de le lancer vous-même. Je dirais qu'envisager une approche différente uniquement si le profilage montre que l'opération de comparaison est une partie chronophage de votre application. Sinon, la facilité de maintenance devrait l'emporter sur les éventuels problèmes de performances.
la source
tuple<>
l »operator<
seraient plus lentement qu'une signature manuscrite.Je suis tombé sur le même problème et ma solution utilise des modèles variadiques c ++ 11. Voici le code:
La partie .h:
Et le .cpp pour le cas de base sans arguments:
Maintenant, votre exemple devient:
la source
À mon avis, vous ne
std::tuple
résolvez toujours pas le même problème que la solution - à savoir, vous devez savoir à la fois combien et le nom de chaque variable membre, vous la dupliquez deux fois dans la fonction. Vous pouvez opter pour l'private
héritage.Cette approche est un peu plus compliquée pour commencer, mais vous ne conservez les variables et les noms qu'au même endroit, au lieu de chaque endroit pour chaque opérateur que vous souhaitez surcharger.
la source
T& one_member(){ return std::get<0>(*this); }
etc? Mais cela n'aurait-il pas besoin de moi pour fournir une telle méthode pour chaque "membre" que j'ai, y compris les surcharges pour la version const et non-const?Si vous prévoyez d'utiliser plus d'une surcharge d'opérateurs, ou plusieurs méthodes de tuple, je vous recommande de faire de tuple un membre de la classe ou de dériver de tuple. Sinon, vous faites beaucoup plus de travail. Lorsque vous décidez entre les deux, une question importante à laquelle il faut répondre est: Voulez-vous que votre classe soit un tuple? Sinon, je recommanderais de contenir un tuple et de limiter l'interface en utilisant la délégation.
Vous pouvez créer des accesseurs pour «renommer» les membres du tuple.
la source
operator<
aidestd::tie
raisonnable? » Je ne comprends pas comment cette réponse se rapporte à cette question.