2010-04-12 3 views
62

Я пытаюсь изменить порядок по умолчанию элементов в множестве целых чисел, чтобы быть лексикографическими вместо числового, и я не могу получить следующий компилировать с г ++:Использования пользовательского станда :: установить компаратор

file.cpp:

bool lex_compare(const int64_t &a, const int64_t &b) 
{ 
    stringstream s1,s2; 
    s1 << a; 
    s2 << b; 
    return s1.str() < s2.str(); 
} 

void foo() 
{ 
    set<int64_t, lex_compare> s; 
    s.insert(1); 
    ... 
} 

Я получаю следующее сообщение об ошибке:

error: type/value mismatch at argument 2 in template parameter list for ‘template<class _Key, class _Compare, class _Alloc> class std::set’ 
error: expected a type, got ‘lex_compare’ 

, что я делаю неправильно?

ответ

107

Вы используете функцию, где вы должны использовать функтор (класс, который перегружает оператор(), поэтому его можно вызвать как функцию).

struct lex_compare { 
    bool operator() (const int64_t& lhs, const int64_t& rhs) const { 
     stringstream s1, s2; 
     s1 << lhs; 
     s2 << rhs; 
     return s1.str() < s2.str(); 
    } 
}; 

Вы затем использовать имя класса в качестве параметра типа

set<int64_t, lex_compare> s; 

Если вы хотите, чтобы избежать шаблонного кода функтора вы также можете использовать указатель на функцию (предполагая, что lex_compare является функцией).

set<int64_t, bool(*)(const int64_t& lhs, const int64_t& rhs)> s(&lex_compare); 
+0

на самом деле моя проблема оказалась дополнительная закрывание> в объявлении набора. Я закрываю вопрос как фиктивный. (с использованием функции прямого действия вместо функтора отлично подходит для STL) –

+0

код в вопросе проще, чем вы предложили (для простого компаратора функций) и работает просто отлично. –

+4

@ Omry: Мне было бы интересно узнать, какой компилятор вы используете: http://codepad.org/IprafuVf – 2010-04-12 09:21:27

14

Ответ Якоби вдохновляет меня написать адаптер для инкапсуляции шаблона функтора.

template< class T, bool (*comp)(T const &, T const &) > 
class set_funcomp { 
    struct ftor { 
     bool operator()(T const &l, T const &r) 
      { return comp(l, r); } 
    }; 
public: 
    typedef std::set< T, ftor > t; 
}; 

// usage 

bool my_comparison(foo const &l, foo const &r); 
set_funcomp< foo, my_comparison >::t boo; // just the way you want it! 

Вау, я думаю, это стоило проблем!

+9

Вопрос, думаю. – 2010-04-12 11:15:33

4

Вы можете использовать функцию компаратора без упаковки его следующим образом:

bool comparator(const MyType &lhs, const MyType &rhs) 
{ 
    return [...]; 
} 

std::set<MyType, bool(*)(const MyType&, const MyType&)> mySet(&comparator); 

, который раздражает впечатать каждый раз, когда вам понадобится набор этого типа, и может вызвать проблемы, если вы не создаете все с таким же компаратором.

7

C++ 11 решение с лямбда и без структур или функции:

auto cmp = [](int a, int b) { return ... }; 
set<int, decltype(cmp)> s(cmp); 

Ideone

+0

тип возврата для лямбда? – user501138

+0

@ user501138, true, если 'a diraria

Смежные вопросы