Какие объекты можно хранить в std::set?

«Какие объекты можно хранить в std::set?» — вопрос из категории STL, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В std::set можно хранить объекты любого типа T, для которых определена строгая слабая упорядоченность (strict weak ordering). По умолчанию для этого используется оператор <. Тип должен быть CopyConstructible или MoveConstructible.

Пример с пользовательской структурой:

struct Employee {
    int id;
    std::string name;
    // Определяем operator< для упорядочивания по id
    bool operator<(const Employee& other) const {
        return id < other.id;
    }
};

int main() {
    std::set<Employee> team;
    team.insert({42, "Alice"}); // Работает благодаря operator<
    team.insert({17, "Bob"});
    // set будет отсортирован: {17, "Bob"}, {42, "Alice"}
}

Альтернатива: пользовательский компаратор. Если нельзя или не нужно менять тип, можно передать функтор сравнения.

struct Employee { int id; std::string name; };

// Компаратор, сравнивающий по имени
struct CompareByName {
    bool operator()(const Employee& a, const Employee& b) const {
        return a.name < b.name;
    }
};

std::set<Employee, CompareByName> teamByName;

Ключевое требование: компаратор должен быть консистентным. Если comp(a, b) == true, то comp(b, a) должен быть false. Нарушение этого правила приведет к неопределенному поведению.