C ++ std :: set пользовательский компаратор

Ну, моя проблема в том, что я использую std :: set с пользовательским компаратором, что-то вроде:

class A
{
public:
A(int x, int y):
_x(x), _y(y)
{
}

int hashCode(){ return (_y << 16) | _x; }

private:
short int _y;
short int _x;
};

struct comp
{
bool operator() (A* g1, A* g2) const
{
return g1->hashCode() < g2->hashCode();
}
};

Итак, я использую это как

std::set<A*, comp> myset;

// Insert some data
A* a = new A(2,1);
A* b = new A(1,3);
myset.insert(a);
myset.insert(b);

Теперь моя проблема в том, что я хотел бы сделать это:

myset.find( (2 << 16) | 1 );

Но, конечно, он исключает A *, а не short int.

Итак, я знаю, что мог бы использовать std :: find_if, но не сделает ли он бесполезным пользовательский компаратор? Это будет перебирать весь список, не так ли? Могу ли я использовать find с hashCode вместо самого объекта?

Спасибо!

0

Решение

set::find принимает аргумент типа key_type (см. обсуждение Почему set :: find не шаблон?). Используя std :: set, вы должны создать временный объект для использования find,

myset.find(A(2, 1));

Если А не дешево построить, вы можете использовать std::map<int, A> (или обертка вокруг этого) вместо этого.

3

Другие решения

Вы не можете сделать это с std::set, так как std::set<>::find является
не (членский) шаблон; Аргумент должен иметь тип ключа.
Для простых классов, подобных вашему, вполне вероятно, что использование
std::vector<A> и сохраняя его отсортированным (используя std::lower_bound
для поиска, и как точка вставки) будет так же быстро.
И с std::lower_boundВы можете перейти в сравнение, а также
используйте любой тип, который вы хотите в качестве ключа. Все, что вам нужно сделать, это убедиться, что
ваш comp класс может обрабатывать сравнения смешанных типов, например:

struct Comp
{
bool operator()( A const&, B const& ) const;
bool operator()( A const&, int ) const;
bool operator()( int, A const& ) const;
};
1

myset.find(&A(2, 1));

Или же

A a(2, 1);
myset.find(&a);
0

Вы определили std::set<A*, comp> myset;, так std::find() должен взять A* аргумент.

std::set<A*, comp> myset;

// Insert some data
A* a = new A(2,1);
A* b = new A(1,3);
myset.insert(a);
myset.insert(b);

Затем вам нужно сделать

myset.find(&A(2,1))

Вернемся к вашему вопросу, std::find() не берет ваш пользовательский компаратор. Вам нужно, на самом деле, использовать std::find_if,

0
По вопросам рекламы [email protected]