8
votes

Triez une STD :: Liste avec myClass :: opérateur <(myClass & Autre)

J'ai un std :: Liste et dans ma classe, j'ai myClass :: opérateur <(myClass & Autre) défini.

J'utilise le std :: list.sort () fonction, mais cela ne change rien dans cette liste. Peut-être qu'il trie juste les pointeurs?

Comment puis-je trier les éléments réels de cette liste?


2 commentaires

Êtes-vous sûr que std :: liste est le bon conteneur pour votre cas d'utilisation? C'est rarement un bon choix; std :: vecteur ou std :: deque fournit généralement des caractéristiques de performance plus favorables. Êtes-vous sûr que vous devez stocker des pointeurs bruts dans le conteneur? C'est aussi rarement un bon choix; Habituellement, il est préférable de stocker vos objets dans le conteneur au lieu des pointeurs et si vous utilisez des pointeurs, des pointeurs intelligents doivent être utilisés.


Remarque: si vous faites opérateur << / code> un membre, il devrait s'agir d'une fonction membre const . Mais généralement, il devrait être un non-membre quand même. Voir Cette entrée de FAQ .


5 Réponses :


2
votes

Ça trier le pointeur comme STD :: Tri (conteneur) Utilisez l'opérateur Vous pouvez transmettre un fonctionnement de comparateur personnalisé à STD :: Trier alors faites une prise prend deux myClass * et renvoyez la comparaison appropriée: P>

template<class T>
struct ptr_comparison
{
   bool operator()(T* a, T* b) { return *a < *b; } 
};

list<myclass*> mylist;

// later

mylist.sort(ptr_comparison<myclass>());


1 commentaires

-1 Pour l'utilisation de std :: Trier sur un std :: Liste . En outre, l'instantantion de pTR_comparision est incorrecte.



13
votes

Vous triez les valeurs du pointeur, pas les valeurs MyClass. Vous devez écrire votre propre prédicat pour comparer les pointeurs par Dréréférence:

struct PPred {
  template <typename T> inline bool operator()(const T * a, const T * b) const
  { return *a < *b; }
};


12 commentaires

Vous pouvez utiliser une fonction au lieu d'une structure. C'est un peu moins verbeux.


Étant donné que vous utilisez const t * , l'OP doit définir une comparaison comme opérateur <(const t &) const .


Etienne: Parfaitement à droite, je pensais que je serais partiellement spécialisé quelque chose sur le chemin, mais ne se révèle pas je ne suis pas. Édition! Nawaz: aussi à droite, édition!


Quelle est la syntaxe pour une "référence constante à un pointeur à t"? :-(


t * const & Il n'y a aucune raison d'utiliser une référence ici, bien que


@James: Juste pour des rires, car les prédicats sont généralement appelés par const-référence ... mais je passerais généralement le pointeur-to-cons-t par copie aussi :-)


@Alf: whoops, typo! Désolé!


J'ai ensuite utilisé myList.sort (pomp ()), mais je suppose que c'est la même chose.


@Quueeuerflow: avec ma version actuelle de l'exemple, myList.sort (pomp ()) ne doit pas fonctionner, car pomp est juste une fonction, pas un nom de classe, et non un nom de classe et Depuis que vous devez spécifier le paramètre de modèle. Seuls myList.sort (pompet ) devrait fonctionner.


Ceci est un autre avantage d'utiliser un objet fonction au lieu d'une fonction: vous pouvez réduire la générosité dans la surcharge de l'opérateur () de sorte que la structure nommée ne soit pas générique. Au lieu d'utiliser pomp , vous pouvez simplement utiliser pomp () .


@James: bon point! J'ai ajouté le code pour le prédicat pour inclure cet aspect.


Méfiez-vous de l'alternative! std :: set est uniquement destiné aux listes uniques. Vous pouvez trouver votre choix vous donnera moins d'articles que vous n'aviez auparavant.



2
votes

En supposant que vous n'avez pas de points nuls dans votre liste, faites

mylist.sort( []( myclass *a, myclass *b ) { return *a < *b } );


1 commentaires

ptrsorter doit renvoyer bool au lieu de vide



4
votes

Plusieurs réponses proposent d'utiliser un prédicat qui prend explicitement deux pointeurs; Cela fonctionnera pour votre cas actuel où vous avez un conteneur de pointes bruts, mais cela ne fonctionnera pas pour aucun autre type déréférenciférable, comme des pointeurs intelligents ou des itérateurs.

Pourquoi ne pas aller à l'itinéraire plus général et correspond à n'importe quel type? < / p> xxx

tandis qu'une référence de const est inutile pour un t * , il est nécessaire pour les types de pointeur intelligents qui sont relativement coûteux à copier (par exemple, std :: partage_ptr ) ou impossible à copier (par exemple, std :: unique_ptr ).

Alternativement, vous pouvez envisager d'utiliser quelque chose comme Boost's indirect_iterator , qui déplace l'indirection dans le itérateur et peut faire un code beaucoup plus propre.


0 commentaires

0
votes

J'essayais de l'exemple du modèle Pompez et puisque les autres classes utiliseraient le pomp, je suis bloqué dans le fichier incluant pour la classe La classe STD :: La liste était tenue. Cependant, quand j'ai compilé la tâche, j'ai obtenu cette tâche: xxx

Le modèle est: xxx

Les appels que j'ai essayés dans fdfttsbfdftbleloadap.c étaient : xxx

ou xxx

t

uniquement lorsque le modèle a été déclaré dans FDFTSBFDFTABLELOADAPPLOP Compiler OK. Alors, comment puis-je obtenir cela pour compiler si le modèle est dans une autre classe, notamment?


1 commentaires

Ceci est une nouvelle question. S'il vous plaît poser une nouvelle question de telle sorte que les gens puissent vous donner une réponse et tout simplement pas de simples commentaires :-).