stl — C ++: использовать собственный класс в мультимножественном контейнере

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

Я хочу добавить свой собственный объект класса в мультимножество контейнера stl и хочу отсортировать его с помощью своего собственного перегруженного оператора less, определенного в моем классе. Я действительно опробовал несколько решений, но ничего не получилось, поэтому я надеюсь, что кто-нибудь может дать мне несколько полезных советов, чтобы решить это.

Вот моя общая идея определения моего класса:

class object {
public:
int first;
string second;

object(int f, string s) {
first = f;
second = s;
}

bool operator<(const object &comp) {
return first < comp.first;
}
};

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

Вот краткий фрагмент кода из моей основной функции:

includes ...
//code omitted
int main() {
multiset<object*> mmset;

mmset.insert(new object(10, "test"));
mmset.insert(new object(11, "test"));

return 0;
}

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

извлечение кода из stl:

// TEMPLATE STRUCT less
template<class _Ty>
struct less : public binary_function<_Ty, _Ty, bool>
{   // functor for operator<
bool operator()(const _Ty& _Left, const _Ty& _Right) const
{   // apply operator< to operands
return (_Left < _Right);
}
};

Я установил точку останова на этой строке и наблюдал, что программа делает здесь, и я не знаю почему, но он только сравнивает адреса из двух объектов и возвращает всегда false. Он никогда не вызывает мой перегруженный оператор less, хотя оператор существует, а переменные _Left и _Right содержат адрес моего объекта.

Буду очень признателен, если кто-нибудь сможет мне помочь.

С наилучшими пожеланиями

Том

3

Решение

Вы не храните objectв вашем multiset, Вы храните object*s. Это указатели на objects. Это означает, что набор упорядочит указатели, которые вы вставляете в него.

Кажется, вы действительно хотите просто multiset<object>:

multiset<object> mmset;
mmset.emplace(10, "test");
mmset.emplace(11, "test");

Теперь это будет использовать < сравнить objectСами.

Если вы действительно хотите хранить указатели, вам нужно предоставить собственный компаратор для multiset, В C ++ 11 вы можете легко сделать это с помощью лямбды:

auto f = [](int* a, int* b) { return *a < *b; };
std::multiset<int*, decltype(f)> mmset(f);

До C ++ 11 вы можете создать функциональный объект, который реализует operator() с тем же телом, что и эта лямбда-функция.

5

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

Спасибо за помощь. Это кажется хорошим решением для решения этой проблемы.

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

Вы можете передать любому конструктору контейнер stl так называемый объект сравнения, который контейнер будет использовать для упорядочения вашего контента.
Единственное, что вам нужно сделать, это определить перегруженный operator() в вашем классе и «неправильно» использовать их как оператор сравнения.

class object {
int first;
string second;

object() { };
object(int f, string s) {
first = f;
second = s;
}

bool operator()(const object *comp1, const object *comp2) const {
return comp1->first < comp2->first;
}
}

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

multiset(object*, object) mmset;

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

1

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