Множество структур
Только начинаю изучать структуры, и в процессе столкнулся с задачей создать set точек, состоящих из 3 координат. Нагуглив, решил что стоит сделать это через структуру. VS никаких ошибок не подчеркивает, но пишет, что не может собрать, когда я пытаюсь заполнить это множество. Подскажите, что я делаю не так? (Скину весь код на всякий случай, может проблема в другом)
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <string>
#include <queue>
#include <deque>
#include <iterator>
using namespace std;
#define ll long long
#define lld long double
#define ull unsigned long long
#define ulld unsigned long double
#define us unsigned short
struct Atom
{
lld x, y, z;
};
int main()
{
setlocale(LC_ALL, "ru");
set <Atom> set_cell;
us cnt_atoms_cell, cellside_x, cellside_y, cellside_z;
cout << "Введите количество атомов в элементарной ячейке: ";
cin >> cnt_atoms_cell;
cout << "Введите размеры сторон элементарной ячейки: ";
cin >> cellside_x >> cellside_y >> cellside_z;
cout << "Введите координаты атомов элементарной ячейки: " << endl;
for (int n = 0; n < cnt_atoms_cell; ++n)
{
Atom atom;
cin >> atom.x >> atom.y >> atom.z;
set_cell.insert(atom);
}
return 0;
}
Ответы (2 шт):
set должен по ходу своей работы сравнивать свои элементы. А как сравнивать ваши атомы?... Так, как описали вы —
как если бы вместо структуры была пара (чтобы сначала сортировалось по 1 значению, потом по второму и т.д.)
можно использовать стандартный tie:
bool operator <(const Atom& a, const Atom& b)
{
return tie(a.x,a.y,a.z) < tie(b.x,b.y,b.z);
}
Но, если хотите, допишите такой оператор сравнения самостоятельно такой, какой вам нужен.
Более того, в set можно передавать разные компараторы, и получать по-разному сортированные множества, а не полагаться на конкретно оператор <.
У вашей структуры нет возможности сравнения. Для того, чтобы её добавить у вас есть два выхода:
- Перегрузить оператор <:
struct Atom
{
lld x, y, z;
bool operator< (const Atom& value) const noexcept {
//ваша реализация сравнения
}
};
- Сделать структуру компаратора/лямбда-функцию и передать её в set:
- Реализация со структурой
struct atom_cmp {
bool operator() (const Atom& v1, const Atom& v2) const noexcept {
//ваша реализация сравнения
}
};
Затем когда создаёте set, пишете:
set<Atom, atom_cmp> set_cell;
- Использовать лямбду:
auto f = [](const Atom& v1, const Atom& v2) {
//ваша реализация
};
set<Atom, decltype(f)> set_cell(f);
Пояснение
Как это всё работает? В первом случае мы просто перегружаем оператор <, который использует компаратор по умолчанию в set. Во втором случае, мы передаём сам компаратор, который имеет только перегруженный оператор () (который и используется set'ом внутри). В случае с лямбдой мы передаём decltype(f), т.к. название класса, к которому относится данная лямбда-функция знает только один компилятор и поэтому мы пишем именно так. decltype(f) обозначает тип объекта f. Помимо этого мы должны передать в конструктор set сам объект f, т.к. у классов лямбд нет конструктора по умолчанию (только конструктор копирования/перемещения)