Введение
Стандарт C++26, официально утвержденный в середине 2025 года, — это не просто очередное инкрементальное обновление. Это целенаправленная консолидация революционных изменений, начатых в C++20 и C++23. Если предыдущие версии добавляли новые фундаментальные возможности (модули, концепты, корутины), то C++26 фокусируется на их интеграции, стабилизации и превращении в единую, целостную систему программирования. Стандарт 2026 года делает современный C++ не только мощнее, но и предсказуемее, безопаснее и, что самое важное, — завершенным для широкого спектра индустриальных задач.
Свершившееся: статическая рефлексия (Static Reflection)
Самое ожидаемое новшество, которое было в черновиках более десяти лет, наконец-то стало частью стандарта (в усеченной, но практичной форме std::reflection).
1.1. Базовый introspection: получение метаданных о типах
#include <reflection> #include <iostream> struct User { int id; std::string name; double balance; }; int main() { // reflection_of<T> - consteval функция, возвращающая meta::info constexpr auto refl = std::reflection::reflection_of<User>; // Получаем список данных-членов как диапазон времени компиляции constexpr auto members = std::reflect::get_data_members(refl); // Итерируемся на этапе компиляции или выполнения std::cout << "Поля класса User:\n"; template for (constexpr auto member : members) { // Получаем имя члена и его тип std::cout << " " << std::reflect::get_name(member) << " : " << std::reflect::get_name(std::reflect::get_type(member)) << "\n"; } // Вывод: // id : int // name : std::string // balance : double }
1.2. Практическое применение: универсальный сериализатор за 20 строк
template<typename T> std::string to_json(const T& obj) { std::string result = "{"; constexpr auto refl = std::reflection::reflection_of<T>; constexpr auto members = std::reflect::get_data_members(refl); bool first = true; template for (constexpr auto member : members) { if (!first) result += ", "; first = false; result += "\"" + std::string(std::reflect::get_name(member)) + "\": "; // Рекурсивная сериализация значения result += serialize_value(std::reflect::get_value(member, obj)); } result += "}"; return result; } // Использование тривиально: User u{42, "Alice", 100.5}; std::cout << to_json(u); // {"id": 42, "name": "Alice", "balance": 100.5}
Контракты (Contracts): безопасность как часть языка
После долгих дебатов контракты вошли в стандарт в упрощенной, но крайне полезной форме через атрибуты [[contract]].
2.1. Атрибуты пред- и постусловий
#include <contract> class BankAccount { double balance = 0; public: // Предусловие: сумма должна быть положительной void deposit(double amount) [[pre: amount > 0, "Deposit amount must be positive"]] [[post old_balance: balance == old_balance + amount]] // old_balance - специальный идентификатор { balance += amount; } // Сложное предусловие с концептом template<typename T> requires std::integral<T> || std::floating_point<T> void transfer_to(BankAccount& other, T amount) [[pre: this != &other, "Cannot transfer to same account"]] [[pre: amount > 0 && amount <= balance, "Insufficient funds or invalid amount"]] [[post: balance == old_balance - static_cast<double>(amount)]] [[post: other.balance == old(other.balance) + static_cast<double>(amount)]] { balance -= amount; other.balance += amount; } }; // Контракты уровня класса (инварианты) class [[invariant: size() >= 0 && capacity() >= size()]] Vector { // ... реализация };
2.2. Режимы проверки и обработка нарушений
// Глобальная настройка через макросы или аргументы компилятора #define CONTRACT_VIOLATION_HANDLER std::contract::violation_handler::terminate // Или: -fcontract-mode=audit (проверки в дебаге) / -fcontract-mode=off (полное отключение в релизе) void process(int* ptr, int size) [[pre: ptr != nullptr]] [[pre: size > 0 && size < 1000]] { // При нарушении контракта: // 1. В режиме аудита (debug) - вызов обработчика (логирование/исключение/завершение) // 2. В режиме off (release) - проверки игнорируются, но могут использоваться для оптимизации for (int i = 0; i < size; ++i) { ptr[i] = i * i; } }
Расширенные возможности для диапазонов (Ranges) и алгоритмов
C++26 завершает переход от пар итераторов к диапазонам как основной абстракции для работы с коллекциями.

