Множество структур

Только начинаю изучать структуры, и в процессе столкнулся с задачей создать 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 шт):

Автор решения: Harry

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 можно передавать разные компараторы, и получать по-разному сортированные множества, а не полагаться на конкретно оператор <.

См. https://ideone.com/w01nY1

→ Ссылка
Автор решения: nyekitka

У вашей структуры нет возможности сравнения. Для того, чтобы её добавить у вас есть два выхода:

  1. Перегрузить оператор <:
struct Atom
{
    lld x, y, z;
    bool operator< (const Atom& value) const noexcept {
        //ваша реализация сравнения
    }
};
  1. Сделать структуру компаратора/лямбда-функцию и передать её в 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, т.к. у классов лямбд нет конструктора по умолчанию (только конструктор копирования/перемещения)

→ Ссылка