Предоставление оператора меньше чем для одного элемента пары - PullRequest
6 голосов
/ 24 февраля 2010

Что было бы самым элегантным способом, тоже исправьте следующий код:

#include <vector>
#include <map>
#include <set>
using namespace std;

typedef map< int, int > row_t;
typedef vector< row_t > board_t;
typedef row_t::iterator area_t;

bool operator< ( area_t const& a, area_t const& b ) {
    return( a->first < b->first );
};

int main( int argc, char* argv[] )
{
    int row_num;
    area_t it;

    set< pair< int, area_t > > queue;
    queue.insert( make_pair( row_num, it ) ); // does not compile
};

Один из способов исправить это - перенести определение менее namespace std (я знаю, вы не должны этого делать. )

namespace std {
    bool operator< ( area_t const& a, area_t const& b ) {
        return( a->first < b->first );
    };
};

Другим очевидным решением является определение меньше, чем <для пара <int, area_t>, но я хотел бы избежать этого и быть возможность определить оператор только для одного элемента пары, где она не определена.

1 Ответ

6 голосов
/ 24 февраля 2010

Когда вы реализуете компаратор, который реализует некоторый специфический и / или довольно экзотический подход сравнения, лучше использовать именованную функцию или объект функции вместо того, чтобы перехватить operator < для этой цели. Я бы сказал, что естественным способом сравнения объекта std::pair было бы использование лексикографического сравнения. Поскольку ваше сравнение не лексикографическое, взятие operator < может быть не очень хорошей идеей. Лучше реализовать класс компаратора

typedef pair< int, area_t > Pair; // give it a more meaningful name

struct CompareFirstThroughSecond {
  bool operator ()(const Pair& p1, const Pair& p2) const { 
    if (p1.first != p2.first) return p1.first < p2.first;
    return p1.second->first < p2.second->first;
  }
};

и используйте его с вашим контейнером

std::set< Pair, CompareFirstThroughSecond > queue;  

(надеюсь, я правильно расшифровал ваше намерение из исходного кода).

Вы также можете реализовать описанный выше метод operator () как шаблонный метод, что делает его пригодным для использования со всеми типами на основе std::pair с итератором в качестве члена second. Это может не иметь никакого смысла, поскольку ваше сравнение достаточно «экзотично».

...