2010-09-13 6 views
1

Je voudrais surcharger la fonction d'échange pour std :: vector des types/objets primitifs. La raison en est un tri lent des vecteurs contenant de gros objets en utilisant std :: sort. Voici l'exemple simple mais ne fonctionnant pas.Tri du vecteur: surcharge swap

#include <vector> 
#include <algorithm> 
class Point 
{ 
private: 
    double x, y; 
public: 
    Point(double xx, double yy) : x(xx), y(yy) {} 

    bool operator < (const Point& p) const 
    { 
     return x < p.x; 
    } 

    void swap(Point &p) 
    { 
     std::swap(*this, p); 
    } 

}; 

namespace std 
{ 
void swap(Point &p1, Point &p2) 
{ 
    p1.swap(p2); 
} 
} 

typedef std::vector<Point> TPoints; 
int main() 
{ 
Point p1(0,0); 
Point p2(7,100); 

TPoints points; 
points.push_back(p1); 
points.push_back(p2); 

    //Overloaded metod swap will not be called 
std::sort(points.begin(), points.end()); 
} 

Malheureusement, lors de la méthode surchargée std :: sort n'est pas appelée. Je suppose que le vecteur contenant des objets sera la même situation ... Merci pour votre aide ...

+1

duplication possible de [Comment surcharger std :: swap()] (http://stackoverflow.com/questions/11562/how-to-overload-stdswap) –

+4

À part toute autre chose, aucune version de 'swap' est appelé parce que vos points sont déjà commandés. –

Répondre

1

Vous devez spécialiser le modèle std::swap, ne pas le surcharger.

Exemple:

namespace std 
{ 
    template<> 
    void swap<Point>(Point &p1, Point &p2) 
    { 
     p1.swap(p2); 
    } 
} 
+0

Un exemple pourrait aider ... Thanx – JohnJ

5

La bonne façon de mettre en œuvre swap est:

class foo 
{ 
public: 
    void swap(foo& pOther) 
    { 
     using std::swap; // enable ADL 
     swap(member1, pOther.member1); // for all members 
    } 
}; 

// allows swap to be found with ADL (place in same namespace as foo) 
void swap(foo& pFirst, foo& pSecond) 
{ 
    pFirst.swap(pSecond); 
} 

// allows swap to be found within std 
namespace std 
{ 
    // only specializations are allowed to 
    // be injected into the namespace std 
    template <> 
    void swap(foo& pFirst, foo& pSecond) 
    { 
     pFirst.swap(pSecond); 
    } 
} 

Cependant, il est logique de le faire lorsque vous devez écrire le Big Three (vous êtes managing some resource).

Vous n'êtes pas, donc je ne vois pas le point. (Tout ce que votre swap fera est de copier autour de certains doubles, tout comme la valeur par défaut std::swap.)

+0

Vous permuter 'member1' avec' other.member1', non? Et pourquoi le préfixe 'p' sur les choses qui ne sont pas des pointeurs, cela signifie-t-il * paramètre * dans votre convention de nommage? –

+0

@Ben Yup et yup. Je ne code pas les informations de type dans les noms de variables (ce qui ne me sert à rien, peu importe le type, je me soucie de ce que cela représente), et j'ai choisi un préfixe 'p' sur les paramètres et le préfixe' m' sur les membres. (Il permet le code comme: 'struct foo {int valeur() const {return valeur mV;} valeur void (int pValue) {mValue = pValue;} int mValue;};' de manière cohérente, sans noms qui s'entrechoquent.) – GManNickG

+0

Ça marche. Merci pour votre réponse. J'ai passé beaucoup de temps à résoudre ce problème, et soudainement la bonne réponse apparaît dans une minute après avoir inséré la question ... – JohnJ

0

Trier appelle probablement la fonction de membre d'échange de vecteur. Vous ne pouvez pas faire ce que vous faites de toute façon, en redéfinissant std :: swap va faire des ravages sous le capot. Plus: êtes-vous sûr que le double, le double compte autant?