🍕 Проекции на поля структур — 10 июля 2026 г. в 10:52:00.872
🍕 Проекции на поля структур В прошлый раз разобрались, что такое проекция и зачем она нужна . Теперь — самый частый сценарий на практике: структура с кучей полей, и алгоритмы хочется гонять по разным из них, не плодя лямбды. struct Person { std::string name; int age; double height; }; std::vector<Person> people = { {"Алиса", 30, 165}, {"Борис", 25, 180}, {"Виктор", 35, 175}, }; 🤠 Одна структура — много ключей Вся прелесть в том, что один и тот же контейнер крутим по любому полю — меняем только &Person::поле: // по возрасту std::ranges::sort(people, std::less{}, &Person::age); // Борис(25), Алиса(30), Виктор(35) // самый высокий auto tallest = std::ranges::max_element(people, std::less{}, &Person::height); std::cout << tallest->name; // Борис // найти по имени auto found = std::ranges::find(people, "Алиса", &Person::name); std::cout << found->age; // 30 Указатель &Person::age годится в проекции, потому что алгоритм зовёт её через std::invoke, а тот превращает его в p.age. Проекцией может быть что угодно вызываемое. Заметьте: max_element и find вернули итератор на целого Person. Проекция выбирает ключ, но на выходе всегда исходный элемент. ‼️ sort сортирует на месте. Гоняете сниппеты подряд по одному people — каждый следующий видит уже переставленный вектор (max_element/find это не волнует). 👑 Компаратор + проекция = направление + ключ Проекция говорит «по какому полю», компаратор — «в каком порядке»: // по убыванию роста std::ranges::sort(people, std::greater{}, &Person::height); // Борис(180), Виктор(175), Алиса(165) std::less → std::greater — перевернули порядок, поле не трогали. Компаратор можно сократить до {}, но не выбросить совсем: std::ranges::sort(people, {}, &Person::age); // ок std::ranges::sort(people, &Person::age); // не компилируется Проекция — третий аргумент, поэтому без компаратора &Person::age уедет в его слот. {} этот слот занимает и подставляет дефолт — а дефолт тут std::ranges::less, не std::less (на наших данных без разницы).

