views:

68

answers:

3

I would like to overload swap function for std::vector of primitive types / objects. The reason is a slow sorting of vectors containing big objects using std::sort. Here is the simple but not working example.

#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());
}

Unfortunately during the std::sort overloaded method is not called. I suppose the vector containing objects will be similar situation... Thanks for yout help...

+1  A: 

You have to specialize the std::swap template, not overload it.

EXAMPLE:

namespace std
{
    template<>
    void swap<Point>( Point &p1, Point &p2)
    {
        p1.swap(p2);
    }
}
Ben Voigt
Some example could help... Thanx
JohnJ
+2  A: 

The proper way to implement swap is:

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);
    }
}

However, it only makes sense to do this when you need to write the Big Three (you're managing some resource).

You aren't, so I don't see the point. (All your swap will do is copy around some doubles, just like the default std::swap would.)

GMan
You'd swap `member1` with `other.member1`, right? And why the `p` prefix on things that aren't pointers, does that mean *parameter* in your naming convention?
Ben Voigt
@Ben Yup and yup. I don't encode type information in variables names (utterly pointless to me; I don't care what type it is, I care about what it represents), and I picked up a `p` prefix on parameters and `m` prefix on members. (It allows code like: `struct foo { int value() const { return mValue; } void value(int pValue) { mValue = pValue; } int mValue; };` in a consistent manner, with no clashing names.)
GMan
It works. Thanx for your answer. I spent a lot of time solving this problem, and suddenly there appears the correct answer in a minute after inserting the question ...
JohnJ
Sorry, I didn't read closely :v( . (Also, it looks like GNU has changed that behavior.)
Potatoswatter
@Potatoswatter: :v( <3
GMan
Almost: `template<> void swap<foo>(...`. But why not use [simpler syntax?](http://stackoverflow.com/questions/11562/how-to-overload-stdswap/2684544#2684544) Why have 3 ways to swap? (free-function in the same namespace, method, specialized std::swap)
Roger Pate
A: 

sort probably calls the swap member function of vector. You cant do what you are doing anyway, redefining std::swap is going to play havoc under the hood.

Plus - are you sure that double, double counts as big?

pm100