Использование пользовательского std:: set compator

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

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’

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

Ответ 1

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

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;

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

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

Ответ 2

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

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!

Ничего себе, я думаю, это стоило проблемы!

Ответ 3

С++ 11 решение с лямбдой и без структуры или функции:

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

Ideone

Ответ 4

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

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

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

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