Векторная сортировка: перегрузка подкачки

Я хотел бы перегрузить функцию подкачки для std::vector примитивных типов/объектов. Причина в медленной сортировке векторов, содержащих большие объекты, с помощью std::sort. Вот простой, но не рабочий пример.

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

К сожалению, во время std::sort перегруженный метод не вызывается. Я полагаю, что вектор, содержащий объекты, будет похожей ситуацией... Спасибо за помощь...


person JohnJ    schedule 13.09.2010    source источник
comment
возможный дубликат Как перегрузить std::swap()   -  person Ben Voigt    schedule 14.09.2010
comment
Помимо всего прочего, никакая версия swap не вызывается, потому что ваши очки уже заказаны.   -  person Steve Jessop    schedule 14.09.2010


Ответы (3)


Правильный способ реализации swap:

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

Однако это имеет смысл делать только тогда, когда вам нужно написать «Большую тройку» (вы управление каким-либо ресурсом).

У тебя нет, так что не вижу смысла. (Все, что ваш swap будет делать, это копировать несколько двойников, как это делает std::swap по умолчанию.)

person GManNickG    schedule 13.09.2010
comment
Вы бы поменяли местами member1 на other.member1, верно? И почему префикс p для вещей, которые не являются указателями, означает ли это параметр в вашем соглашении об именах? - person Ben Voigt; 14.09.2010
comment
@ Бен Да и да. Я не кодирую информацию о типе в именах переменных (для меня это совершенно бессмысленно; мне все равно, какой это тип, мне важно, что он представляет), и я взял префикс p для параметров и префикс m для членов. (Это позволяет использовать код типа: struct foo { int value() const { return mValue; } void value(int pValue) { mValue = pValue; } int mValue; }; согласованным образом, без конфликтующих имен.) - person GManNickG; 14.09.2010
comment
Оно работает. Спасибо за ваш ответ. Я потратил много времени на решение этой задачи, и вдруг появляется правильный ответ через минуту после вставки вопроса... - person JohnJ; 14.09.2010
comment
Извините, я не внимательно читал :v( . (Кроме того, похоже, что GNU изменила это поведение.) - person Potatoswatter; 14.09.2010
comment
Почти: template<> void swap<foo>(.... Но почему бы не использовать более простой синтаксис? Почему есть 3 способа обмена? (свободная функция в том же пространстве имен, метод, специализированный std::swap) - person ; 15.09.2010

Вы должны специализировать шаблон std::swap, а не перегружать его.

ПРИМЕР:

namespace std
{
    template<>
    void swap<Point>( Point &p1, Point &p2)
    {
        p1.swap(p2);
    }
}
person Ben Voigt    schedule 13.09.2010
comment
Какой-то пример может помочь... Спасибо - person JohnJ; 14.09.2010

sort, вероятно, вызывает функцию-член swap вектора. Вы все равно не можете делать то, что делаете, переопределение std::swap приведет к хаосу под капотом.

Плюс - ты уверен, что двойной, двойной считается большим?

person pm100    schedule 13.09.2010