Mettre en place des opérateurs de comparaison via «tuple» et «tie», une bonne idée?

(Note: tuple et tie peuvent être tirés de Boost ou C ++ 11.)
Lors de l’écriture de petites structures avec seulement deux éléments, j’ai parfois tendance à choisir une std::pair , car tout ce qui est important est déjà fait pour ce type de données, comme l’ operator< pour le classement ssortingct-faible.
Les inconvénients sont les noms de variables à peu près inutiles. Même si j’ai créé moi-même ce typedef , je ne me souviendrai pas de 2 jours plus tard quelle était la first et la second , surtout si elles sont toutes les deux du même type. Cela devient encore pire pour plus de deux membres, car le pair nicheur est à peu près nul.
L’autre option pour cela est un tuple , soit de Boost, soit de C ++ 11, mais cela ne semble pas vraiment plus beau et plus clair. Donc, je retourne à l’écriture des structures moi-même, y compris les opérateurs de comparaison nécessaires.
Etant donné que l’ operator< peut être particulièrement encombrant, j’ai pensé à contourner tout ce désordre en s’appuyant uniquement sur les opérations définies pour tuple :

Exemple d’ operator< , par exemple pour un classement ssortingct-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 un tuple de T& références des arguments passés.)


Edit : La suggestion de @DeadMG d’hériter en privé de tuple n’est pas mauvaise, mais elle a quelques inconvénients:

  • Si les opérateurs sont autonomes (éventuellement des amis), je dois hériter publiquement
  • Avec le casting, mes fonctions / opérateurs ( operator= spécifiquement) peuvent être facilement contournés
  • Avec la solution tie , je peux laisser de côté certains membres s’ils ne comptent pas pour la commande

Y at-il des inconvénients dans cette mise en œuvre que je dois prendre en compte?

Cela va certainement faciliter l’écriture d’un opérateur correct plutôt que de le faire vous-même. Je dirais que seule une approche différente peut être envisagée si le profilage montre que l’opération de comparaison prend beaucoup de temps. Sinon, la facilité de maintenance devrait l’emporter sur les problèmes de performances éventuels.

J’ai rencontré ce même problème et ma solution utilise des modèles variadic c ++ 11. Voici le code:

La partie .h:

 /*** * Generic lexicographical less than comparator written with variadic templates * Usage: * pass a list of arguments with the same type pair-wise, for intance * lexiLessthan(3, 4, true, false, "hello", "world"); */ bool lexiLessthan(); template bool lexiLessthan(const T &first, const T &second, Args... rest) { if (first != second) { return first < second; } else { return lexiLessthan(rest...); } } 

Et le .cpp pour le cas de base sans arguments:

 bool lexiLessthan() { return false; } 

Maintenant, votre exemple devient:

 return lexiLessthan( lhs.one_member, rhs.one_member, lhs.another, rhs.another, lhs.yet_more, rhs.yet_more ); 

À mon avis, vous n’abordez toujours pas le même problème que les solutions std::tuple , à savoir que vous devez connaître le nombre et le nom de chaque variable membre, vous la dupliquez deux fois dans la fonction. Vous pouvez opter pour private inheritance private .

 struct somestruct : private std::tuple<...> { T& GetSomeVariable() { ... } // etc }; 

Cette approche est un peu plus compliquée au départ, mais vous ne conservez que les variables et les noms au même endroit, au lieu de tous les opérateurs que vous souhaitez surcharger.

Si vous prévoyez d’utiliser plus d’une surcharge d’opérateur, 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, ce que vous faites est beaucoup plus de travail. En décidant entre les deux, une question importante à 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.