C ++, компаратор, указатель на функцию - PullRequest
2 голосов
/ 13 ноября 2010

Я хотел бы создать отсортированный набор точек по координатам x или y.

typedef std::set <Point2D, sorter> Points;

Для типа «Точка» я хотел бы использовать другие компараторы. Первый сортирует точки по координатам x, второй по координатам y:

typedef std::set <Point2D, sortPointsByX()> Points;
typedef std::set <Point2D, sortPointsByy()> Points;

где

class sortPoints2DByX
{
    public:

            bool operator() ( const Point2D &p1, const Point2D &p2 );

};

class sortPoints2DByY
{
    public:

            bool operator() ( const Point2D &p1, const Point2D &p2 );

};

Возможно ли создать указатель на конструктор классов sortPoints2DByX / sortPoints2DByY в объявлении Points

typedef std::set <Point2D, pointer_to_somparator_class> Points;

а по необходимости использовать любой из них?

Мне нужно, чтобы один тип данных можно было сортировать двумя способами.

Если эта идея неверна, есть ли более подходящее решение?

Мне нужно вычислить медиану координат x и y ...

Спасибо за вашу помощь ...

Ответы [ 2 ]

2 голосов
/ 14 ноября 2010

Можно ли создать указатель на конструктор классов sortPoints2DByX / sortPoints2DByY в объявлении Points?

Нет, вы не можете взять адрес конструктора класса.

Мне нужно, чтобы один тип данных можно было сортировать двумя способами.

Вы можете обойти использование указателей на функции.Пример реализации:

#include <algorithm>
#include <set>
#include <iostream>

    // Your implementation may differ.
struct Point
{
    int x; int y;
    Point(int x_, int y_)
        : x(x_), y(y_) {}
};

    // For display purposes.
void print(const Point& point)
{
    std::cout << '(' << point.x
        << ',' << point.y << ')' << std::endl;
}

bool OrderByX ( const Point& lhs, const Point& rhs )
{
    return (lhs.x < rhs.x);
}

bool OrderByY ( const Point& lhs, const Point& rhs )
{
    return (lhs.y < rhs.y);
}

    // Type of comparison operator.
typedef bool(*Comparator)
    (const Point&lhs,const Point&rhs);

    // Set used to store points in sorted order.
typedef std::set<Point, Comparator> Points;

int main ( int, char ** )
{
        // Each set ordered with it's own criteria.
    Points by_x(&OrderByX);
    Points by_y(&OrderByY);

        // Insert each point in both sets.
    by_x.insert(Point(1,2)); by_y.insert(Point(1,2));
    by_x.insert(Point(3,1)); by_y.insert(Point(3,1));
    by_x.insert(Point(4,3)); by_y.insert(Point(4,3));
    by_x.insert(Point(2,4)); by_y.insert(Point(2,4));

        // Show that 1st set is in proper order.
    std::cout << "Sorted by X:" << std::endl;
    std::for_each(by_x.begin(), by_x.end(), &print);
    std::cout << std::endl;

        // Show that 2nd set is in proper order.
    std::cout << "Sorted by Y:" << std::endl;
    std::for_each(by_y.begin(), by_y.end(), &print);
    std::cout << std::endl;
}

Генерирует следующий вывод:

Sorted by X:
(1,2)
(2,4)
(3,1)
(4,3)

Sorted by Y:
(3,1)
(1,2)
(4,3)
(2,4)
0 голосов
/ 13 ноября 2010

У меня есть два решения, оба из которых были протестированы:

Во-первых, общий код для обоих:

class Point2D {
 public:
   Point2D(int x, int y) : x_(x), y_(y) { }

   int getX() const { return x_; }
   int getY() const { return y_; }

 private:
   int x_, y_;
};

И основная функция ...

int main(int argc, char *argv[])
{
   Points s1(compareByX);
   Points s2(compareByY);
   const int size = 1750;

   for (int x = -size; x <= size; ++x) {
      for (int y = -size; y <= size; ++y) {
         Point2D p(x, y);
         s1.insert(p);
         s2.insert(p);
      }
   }
   return 0;
}

Теперь для решения 1:

#include <tr1/functional>
#include <set>

typedef ::std::tr1::function<bool (const Point2D &, const Point2D &)> comparefunc_t;
typedef ::std::set <Point2D, comparefunc_t> Points;

bool compareByX(const Point2D &a, const Point2D &b)
{
   return (a.getX() != b.getX()) ?
      (a.getX() < b.getX()) : (a.getY() < b.getY());
}

bool compareByY(const Point2D &a, const Point2D &b)
{
   return (a.getY() != b.getY()) ?
      (a.getY() < b.getY()) : (a.getX() < b.getX());
}

И гораздо более длинное решение 2:

class Point2DComparator {
 public:
   virtual bool operator()(const Point2D &a, const Point2D &b) const = 0;

 protected:
   const Point2DComparator &operator =(const Point2DComparator &b) {
      return *this;
   }
   Point2DComparator(const Point2DComparator &b) { }
   Point2DComparator() { }
};

class Point2DComparatorEnvelope : public Point2DComparator {
 public:
   Point2DComparatorEnvelope(const Point2DComparator &letter)
        : letter_(letter)
   {
   }

   virtual bool operator()(const Point2D &a, const Point2D &b) const {
      return letter_(a, b);
   }

 private:
   const Point2DComparator &letter_;
};

class XComparator : public Point2DComparator {
 public:
   virtual bool operator() ( const Point2D &a, const Point2D &b) const {
      return (a.getX() != b.getX()) ?
              (a.getX() < b.getX()) : (a.getY() < b.getY());
   }
};

class YComparator : public Point2DComparator {
 public:
   virtual bool operator() ( const Point2D &a, const Point2D &b) const {
      return (a.getY() != b.getY()) ?
              (a.getY() < b.getY()) : (a.getX() < b.getX());
   }
};

typedef ::std::set<Point2D, Point2DComparatorEnvelope> Points;
XComparator compareByX;
YComparator compareByY;

Они кажутся виртуальными (не каламбур) идентичны по производительности.Второе намного сложнее, хотя, если вы посмотрите на внутреннюю часть ::std::tr1::function, вы увидите, что она очень волосатая.Второй в основном полезен для демонстрационных целей.ИМХО, стандарт нарушен за требование взломать конверт / письмо, чтобы все это работало.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...