Vous pouvez passer un pointeur de fonction, un objet fonction (ou amplifier lambda) à std :: sort pour définir un ordre faible strict des éléments du conteneur que vous voulez trier.Chaînage de prédicats de classement (par exemple pour std :: sort)
Cependant, parfois (assez que j'ai touché cela plusieurs fois), vous voulez être en mesure d'enchaîner les comparaisons "primitives".
Un exemple trivial serait si vous étiez en train de trier une collection d'objets qui représentent des données de contact. Parfois, vous voudrez trier par
last name, first name, area code. Autres fois
first name, last name- encore d'autres fois
age, first name, area code... etc
Maintenant, vous pouvez certainement écrire un objet fonction supplémentaire pour chaque cas, mais cela viole le principe DRY - surtout si chaque comparaison est moins triviale.
Il semble que vous devriez être capable d'écrire une hiérarchie de fonctions de comparaison - les bas niveau font les comparaisons simples et primitives (par ex. Prénom < prénom), puis celles de niveau supérieur appellent les fonctions de niveau inférieur (chaînage probable avec & & pour utiliser l'évaluation de court-circuit) pour générer les fonctions composites.
Le problème avec cette approche est que std :: sort prend un prédicat binaire - le prédicat ne peut retourner qu'un booléen. Donc, si vous les composez, vous ne pouvez pas dire si un "faux" indique une égalité ou supérieur à. Vous pouvez faire en sorte que vos prédicats de niveau inférieur renvoient un int, avec trois états - mais alors vous devrez envelopper ces prédicats de niveau supérieur avant qu'ils puissent être utilisés avec std :: sort par eux-mêmes.
En tout, ce ne sont pas des problèmes insurmontables. Cela semble juste plus difficile que cela devrait être - et invite certainement une implémentation de bibliothèque auxiliaire.
Par conséquent, est-ce que quelqu'un sait d'une bibliothèque préexistante (en particulier s'il s'agit d'une bibliothèque std ou boost) qui peut aider ici - d'avoir d'autres idées sur le sujet?
[Mise à jour]
Comme mentionné dans certains commentaires - je suis allé de l'avant et écrit ma propre mise en œuvre d'une classe pour gérer cela. C'est assez minime, et a probablement quelques problèmes avec cela en général. mais sur cette base, pour toute personne intéressée, la classe est ici:
Et certaines fonctions d'aide (pour éviter la nécessité de préciser args modèle) est ici:
Le problème avec cette implémentation est que vos fonctions de comparaison de bas niveau renvoient des booléens. Vous voulez seulement passer à la prochaine comparaison si le test actuel compare * égal *. – philsquared
Voir mon propre coup à ce que j'ai posté un lien dans dans ma réponse à siukurnin, ci-dessus. Je peux maintenant faire: std :: sort (c.begin(), c.end(), MakeCompareChain (f1, f2, f3)); – philsquared
Non, cela fonctionne - nous avons juste besoin de faire deux comparaisons (a == b est le même que non (a