Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.94/18: Рейтинг темы: голосов - 18, средняя оценка - 4.94
0 / 0 / 0
Регистрация: 11.08.2015
Сообщений: 123

Std::set с кастомным классом, как правильно перегрузить оператор < ?

11.11.2018, 13:42. Показов 3890. Ответов 48
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток, у меня имееться такой класс:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Truck
{
    public:
        size_t getNumber();
        Truck() = delete;
        Truck(size_t, std::string);
        ~Truck() = default;
        bool operator<(const Truck& rhs)const
        {
           return (number < rhs.number);  
        }
    private:
        QString tr_name;
        size_t number;
        std::map<std::string,int> data;
};
я пытаюсь вставить в него елемент
C++
1
2
3
size_t tmp1=s1.at(0).toInt();
std::string tmp2 = s1.at(1).toStdString();
trucks.emplace(tmp1, tmp2);
trucks выглядит так:
C++
1
std::set<Truck> trucks;
но у меня всеравно выдает ошибку :/
p.s. кто-то может еще подсказать почему в методе bool operator<(const Truck& rhs)const, метод getNumber() я не могу вызвать.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
11.11.2018, 13:42
Ответы с готовыми решениями:

Как правильно перегрузить оператор [] =
вот например в классе хранится массив, и допустим я хочу елементу массива в этом классе присвоить другое значение, тоесть так, class...

Как правильно перегрузить оператор для шаблона класса
Имеется такой шаблон: template&lt;int Low = 0, int High = 1000&gt; class Diapazon { }; Внутри него много всего, что уже работает,...

Как правильно перегрузить оператор умножения числа на матрицу?
У меня возникла такая проблема я не могу перезагрузить оператор умножения числа на матрицу, матрицу на число я умножил верно, а вот число...

48
166 / 109 / 57
Регистрация: 30.08.2018
Сообщений: 357
11.11.2018, 14:26
Вот сюда просится const
Цитата Сообщение от Smeh_ Посмотреть сообщение
size_t getNumber();
Сделать метод костантным и всё должно заработать

C++
1
2
3
4
size_t Truck::getNumber() const
{
    return number;
}
1
0 / 0 / 0
Регистрация: 11.08.2015
Сообщений: 123
11.11.2018, 14:49  [ТС]
А не могли бы подсказать, почему у меня на emplace ругается?
И почему с использованием слова const метод начинает видеть, хотя он по идеи public?
Похожая проблема и с другим методом
C++
1
2
 auto ret = trucks.emplace(tmp1, truck_n.at(1));       
        ret.first->addTimeWeight(time, weight);
вот немного разширенный класс:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Truck
{
    public:
        size_t getNumber()const;
        Truck() = delete;
        Truck(size_t, QString);
        ~Truck() = default;
        void addTimeWeight(QString, QString);
        bool operator<(const Truck& rhs)const
        {
           return (number < rhs.getNumber());
        }
    private:
        size_t number;
        QString tr_name;
        std::map<std::string,int> data;
};
0
166 / 109 / 57
Регистрация: 30.08.2018
Сообщений: 357
11.11.2018, 14:56
Цитата Сообщение от Smeh_ Посмотреть сообщение
А не могли бы подсказать, почему у меня на emplace ругается?
Текст ошибки покажите.
Нужно больше кода.
код который показываете рабочий.

Добавлено через 1 минуту
Цитата Сообщение от Smeh_ Посмотреть сообщение
И почему с использованием слова const метод начинает видеть
Константный метод видит другой константный метод

Добавлено через 41 секунду

Не по теме:

Smeh_, ушел по делам, сори

0
0 / 0 / 0
Регистрация: 11.08.2015
Сообщений: 123
11.11.2018, 15:08  [ТС]
вот класс главного окна(руки из жопы не могу в спойлер засунуть :/ ):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private slots:
    void openFile();
    void saveFile();
    void closeFile();
    void parseFile();
private:
    void createActions();
    void createMenus();
    Ui::MainWindow *ui;
    QMenuBar *mainMenu;
    QMenu *fileMenu;
    QMenu *sqlMenu;
    QTextBrowser *txtBrw;
    QPushButton *parseBtn;
 
    QAction *openAct;
    QAction *saveAct;
    QAction *closeAct;
 
    QFile *file;
    std::set<Truck> trucks;
};

Вот метод в котором проблемы с emplace и возвращаемым std:: pair:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void MainWindow::parseFile()
{
    QRegExp reg("\\,");
    QString s = txtBrw->toPlainText();
    QTextStream in(&s);
    while(!in.atEnd())
    {
        QString line = in.readLine();
        QStringList list = line.split(reg);
 
        auto time = list[0];
        auto weight = list[2];
 
        QStringList truck_n = list.at(1).split(QRegExp("\\s+"),QString::SkipEmptyParts);
        size_t tmp1=truck_n.at(0).toInt();
        std::string tmp2 = truck_n.at(1).toStdString();
        auto ret = trucks.emplace(tmp1, truck_n.at(1));
        ret.first->addTimeWeight(time, weight);
    }
}
А вот сами ошибки:
mainwindow.obj:-1: error: LNK2019: unresolved external symbol "public: unsigned int __thiscall Truck::getNumber(void)const " (?getNumber@Truck@@QBEIXZ) referenced in function "public: bool __thiscall Truck::operator<(class Truck const &)const " (??MTruck@@QBE_NABV0@@Z)

mainwindow.obj:-1: error: LNK2019: unresolved external symbol "public: __thiscall Truck::Truck(unsigned int,class QString)" (??0Truck@@QAE@IVQString@@@Z) referenced in function "public: void __thiscall std::allocator<struct std::_Tree_node<class Truck,void *> >::construct<class Truck,unsigned int &,class QString const &>(class Truck *,unsigned int &,class QString const &)" (??$construct@VTruck@@AAIABVQString@@@?$ allocator@U?$_Tree_node@VTruck@@PAX@std@ @@std@@QAEXPAVTruck@@AAIABVQString@@@Z)

mainwindow.obj:-1: error: LNK2019: unresolved external symbol "public: void __thiscall Truck::addTimeWeight(class QString,class QString)const " (?addTimeWeight@Truck@@QBEXVQString@@0@Z ) referenced in function "private: void __thiscall MainWindow:arseFile(void)" (?parseFile@MainWindow@@AAEXXZ)
0
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
11.11.2018, 15:14
Цитата Сообщение от Smeh_ Посмотреть сообщение
Truck(size_t, std::string);
Приведите код конструктора.
0
0 / 0 / 0
Регистрация: 11.08.2015
Сообщений: 123
11.11.2018, 15:17  [ТС]
Вот конструктор.
C++
1
2
3
4
Truck::Truck(size_t numb, QString name):number(numb), tr_name(name)
{
 
}
0
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
11.11.2018, 15:22
Smeh_, так он у Вас принимает QString или std::string? Измените реализацию на std::string.
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
11.11.2018, 15:25
Smeh_, а вы файл с реализацией методов класса Truck не забыли в проект добавить?
0
0 / 0 / 0
Регистрация: 11.08.2015
Сообщений: 123
11.11.2018, 15:30  [ТС]
во втором сообщении я поменял std::string на QString

Добавлено через 1 минуту
в файле mainwindow.hpp

C++
1
2
3
4
5
6
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
#include "truck.h"
#include <set>
Или Вы о другом?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
11.11.2018, 15:44
Цитата Сообщение от Smeh_ Посмотреть сообщение
Или Вы о другом?
Я о другом.
Раз вы не поняли о чем, то похоже действительно не добавили.
Файл truck.cpp у вас в pro-файле прописан?
0
0 / 0 / 0
Регистрация: 11.08.2015
Сообщений: 123
11.11.2018, 15:46  [ТС]
По идеи прописан :/

SOURCES += \
main.cpp \
mainwindow.cpp \
truck.cpp

HEADERS += \
mainwindow.h \
truck.h
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
11.11.2018, 15:53
Smeh_, У вас линковщик не может найти определения функций. Так бывает, если файл с определениями не участвует в сборке. Возможно стоит перегенерировать сборку из pro.
1
0 / 0 / 0
Регистрация: 11.08.2015
Сообщений: 123
11.11.2018, 16:04  [ТС]
Верите или нет, я вызвал Clean All по многу раз и Build all, сейчас в QtCreatore вызвал "run qmake" и эта дура перестала ругаться :/
Спасибо.
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
11.11.2018, 16:33
Цитата Сообщение от Smeh_ Посмотреть сообщение
Верите или нет, я вызвал Clean All по многу раз и Build all, сейчас в QtCreatore вызвал "run qmake" и эта дура перестала ругаться :/
Верю. Я поэтому вам и сказал
Цитата Сообщение от DrOffset Посмотреть сообщение
Возможно стоит перегенерировать сборку из pro.
0
0 / 0 / 0
Регистрация: 11.08.2015
Сообщений: 123
11.11.2018, 17:18  [ТС]
А не могли бы Вы мне помочь в другом вопросе?

C++
1
2
 auto ret = trucks.emplace(tmp1, truck_n.at(1).toStdString());
        ret.first->addTimeWeight(time, weight);
в данном коде чтобы не вылазила ошибка, я сделал метод addTimeWeight, в классе Truck - const, но теперь при попытке сделать:
C++
1
2
3
4
  void Truck::addTimeWeight(QString time, QString weight)const
 {
    data.emplace(std::make_pair(time.toStdString(), weight.toInt()));
 }
вилазит ошибка:
C:\Project\viz_tz\truck.cpp:16: error: C2662: 'std:: pair<std::_Tree_iterator<std::_Tree_val< std::_Tree_simple_types<std:: pair<const _Kty,_Ty>>>>,bool> std::_Tree<std::_Tmap_traits<_Kty,_Ty,_P r,_Alloc,false>>::emplace<std:: pair<std::basic_string<char,std::char_tr aits<char>,std::allocator<char>>,int>>(s td:: pair<std::basic_string<char,std::char_tr aits<char>,std::allocator<char>>,int> &&)': cannot convert 'this' pointer from 'const std::map<std::string,int,Comp,std::alloc ator<std:: pair<const _Kty,_Ty>>>' to 'std::_Tree<std::_Tmap_traits<_Kty,_Ty,_ Pr,_Alloc,false>> &'
with
[
_Kty=std::string,
_Ty=int,
_Pr=Comp,
_Alloc=std::allocator<std:: pair<const std::string,int>>
]
and
[
_Kty=std::string,
_Ty=int
]
and
[
_Kty=std::string,
_Ty=int,
_Pr=Comp,
_Alloc=std::allocator<std:: pair<const std::string,int>>
]

карта data имеет вид:
C++
1
  std::map<std::string,int,Comp> data;
Comp:
C++
1
2
3
4
5
6
7
struct Comp
{
  bool operator()(const std::string& lhs, const std::string& rhs)
  {
    return lhs.size()<rhs.size();//посже тут будет другая имплементация
  }
};
А то я уже несколько часов пытаюсь понять в чём дело, и жонглирую "const" :/
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
11.11.2018, 20:59
Цитата Сообщение от Smeh_ Посмотреть сообщение
я сделал метод addTimeWeight, в классе Truck - const
Однако const в методе означает, что этот метод не меняет содержимое объекта, что противоречит тому, что ты в этом методе делаешь.

Добавлено через 3 минуты
Цитата Сообщение от Smeh_ Посмотреть сообщение
ытаюсь понять в чём дело, и жонглирую "const"
Убери его из всех методов, где происходит изменение соотвествующих объектов.

Цитата Сообщение от Smeh_ Посмотреть сообщение
bool operator()(const std::string& lhs, const std::string& rhs)
А вот тут const бы не помешал.
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
11.11.2018, 21:50
Цитата Сообщение от Smeh_ Посмотреть сообщение
в данном коде чтобы не вылазила ошибка, я сделал метод addTimeWeight, в классе Truck - cons
Ключ в map/set всегда константный. При использовании std::set, да, бывает такая проблема, что если тип объекта, используемый в качестве ключа, сложный и содержит еще какую-то постороннюю логику, то методы, взаимодействующие с этой логикой, приходится делать const, что выглядит, мягко скажем, некрасиво.

Если вы гарантируете, что данные, которые вы меняете, не влияют на сортировку в set, то можете сделать вашу data mutable. Однако это в целом плохое решение, т.к. вынуждает в коде писать неинтуитивные вещи: метод добавляет нечто в объект, но сам он при этом const. Хорошего решения этой ситуации с использованием std::set нет. Можно использовать другие контейнеры, которые позволяют указывать что конкретно в объекте является ключом, освобождая остальную его часть от необходимости быть const (вроде boost::multi_index), или разбить свой класс на ключ и данные, и перейти на std::map.

Цитата Сообщение от Smeh_ Посмотреть сообщение
А то я уже несколько часов пытаюсь понять в чём дело, и жонглирую "const" :/
Это очень плохо, что жонглируете. Надо понять, а не делать наугад.
2
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
11.11.2018, 22:04
DrOffset,
В этом плане логика std::set мне не понятна
Назвали значение ключом и сказали что ключи менять нельзя
Да, можно удалить "ключ" и добавить новый, но что мешает позволить менять сам элемент?
Реализацию нормальную не придумали поэтому и запретили?)
Я просто логику понять не могу
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9006 / 4707 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
11.11.2018, 22:51
Цитата Сообщение от Undisputed Посмотреть сообщение
но что мешает позволить менять сам элемент
Элемент и есть ключ. Беда в том, что если идентификация использует лишь часть объекта, то всё едино если объект ключ, то он весь константен. Следовательно может вызвать лишь конст методы. Тогда, чтобы изменить поле которое не относится к "ключевому" набору, то его нужно сделать mutable. Или выдрать из объекта ключевые поля (создав отдельный константный объект). Это - совсем больная мысль.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
11.11.2018, 22:51
Помогаю со студенческими работами здесь

Перегруженный оператор () для std::set
Зачем в СТЛ в контейренах типу SET и других перегружать оператор () вот код struct WordEntryLessById { bool operator ()...

Ошибка со списком с кастомным классом
Есть один список с кастомным классом gameObject. Прототип в game.h: extern std::list&lt;gameObject&gt; gameObjectList; Объявление в...

STL std::set, std::pair, std::make_pair
Я не знаю как описать тему в двух словах, поэтому не обращайте внимание на название темы. Собственно перейдем к нашим баранам: есть...

Как перегрузить методы, чтобы получились аналоги get set из C#
Как можно перегрузить методы, что бы получился аналог get set из C#. Т.е. что то такое: class A { private: int count;...

Как перегрузить оператор<< и оператор>> ?
Доброго времени суток. Застрял на двух вопросах и не как не могу найти инфу которвя мне помогла бы их решить. вопрос первый. В общем...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru