Утверждён стандарт C++26

Комитет ISO по стандартизации языка C++ утвердил финальный вариант спецификации, образующей международный стандарт «C++26». Представленные в спецификации возможности частично уже поддерживаются в компиляторах GCC (gnu.org), Clang и Microsoft Visual C++. Поддерживающие C++26 стандартные библиотеки реализованы в рамках проекта Boost.
В следующие два месяца утверждённая спецификация будет находиться на стадии подготовки документа к публикации, на которой будет проведена работа по редакторской правке орфографических ошибок и опечаток. В начале ноября результирующий вариант документа будет направлен в ISO для публикации под формальным именем ISO/IEC 14882:2026.
Основные особенности C++26:
- Реализованы элементы контрактного программирования (Contracts), позволяющие определять формальные спецификации интерфейсов при помощи трёх новых операторов:
pre(предусловие),post(постусловие) иcontract_assert(проверка утверждения). Операторpreопределяет предварительные условия, которые должны быть выполнены перед вызовом (проверка входных данных);post— условия, которые должны соблюдаться после выполнения (требования к выходным данным);contract_assert— условия возникновения исключений. Возможность появится в GCC 16.
int f(const int x)
pre (x != 1) // требования ко входным данным
post (r : r == x && r != 2) // требования к результату; r - значение с результатом
{
contract_assert (x != 3);
return x;
}
- Добавлена поддержка рефлексии (Reflection), позволяющей отслеживать и модифицировать элементы программы на стадии компиляции. Добавлены новые операторы »^^ (open-std.org)» для получения метаинформации о грамматической конструкции и »[: …:]» для выполнения обратного преобразования. Для преобразования и обработки полученной в ходе инспектирования информации предложена библиотека
std::metaи доступны такие возможности, как вычисления с константами. Поддержка рефлексии будет добавлена в GCC 16.
constexpr int i = 42, j = 42;
constexpr std::meta::info r = ^^i, s = ^^i;
static_assert(r == r && r == s);
static_assert(^^i != ^^j); // 'i' и 'j' имеют различные значения.
static_assert(constant_of(^^i) == constant_of(^^j)); // 'i' и 'j' одинаковы
static_assert(^^i != std::meta::reflect_constant(42)); // отличается от значения 42
- Добавлен оператор «template for» для перебора элементов, таких как пакеты параметров, похожие на кортежи объекты и результаты рефлексии (метаобъекты), на этапе компиляции в стиле обычного цикла. При выполнении
template forтело цикла раскрывается для каждого элемента и каждая итерация обрабатывается в отдельной области видимости, в которой меняющаяся в цикле переменная является константой. В контексте рефлексииtemplate forможет применяться для обхода свойств классов или перечислений. Возможность появится в GCC 16.
void f() {
template for (constexpr int I : std::array{1, 2, 3}) {
static_assert(I < 4);
}
}
будет раскрыто в:
void f() {
{
constexpr auto&& __range = std::array{1, 2, 3};
constexpr auto __begin = __range.begin();
constexpr auto __expansion-size = __range.end() - __begin; // 3
{
constexpr int I = *(__begin + 0);
static_assert(I < 4);
}
{
constexpr int I = *(__begin + 1);
static_assert(I < 4);
}
{
constexpr int I = *(__begin + 2);
static_assert(I < 4);
}
}
}
- Добавлен фреймворк std: execution для асинхронного и параллельного выполнения кода. Предоставляются объекты
scheduler, определяющий планировщик выполнения работ (поток, пул потоков, GPU, event loop),sender, определяющий выполняемую работу, иreceiver— обработчик результата.
using namespace std::execution;
scheduler auto sch = thread_pool.scheduler();
sender auto begin = schedule(sch);
sender auto hi = then(begin, []{
std::cout < "Hello world! Have an int.";
return 13;
});
sender auto add_42 = then(hi, [](int arg) { return arg + 42; });
auto [i] = this_thread::sync_wait(add_42).value();
- Добавлена библиотека std: simd для распараллеливания выполнения операций над данными при помощи наборов инструкций SIMD, таких как AVX-512 и NEON, с использованием стандартной системы типов C++.
std::simd a = {1.0f, 2.0f, 3.0f, 4.0f};
std::simd b = {5.0f, 6.0f, 7.0f, 8.0f};
std::simd result = a + b;
- Предложена реализация вектора (массива) переменного размера std: inplace_vector, размещаемого в стеке, размер которого определяется на этапе компиляции. API близок к
std::vector, но элементы массива хранятся не в «куче», а внутри объекта.
inplace_vector a(10);
inplace_vector b(std::move(a));
assert(a.size() == 10);
- Добавлена директива »#embed», предназначенная для встраивания в код бинарных ресурсов.
const unsigned char icon_display_data[] = {
#embed "art.png"
};
- Добавлена поддержка генерации и обработки исключений на этапе компиляции при ошибках в контексте
constexpr.
constexpr std::optional checked_divide(unsigned n, unsigned d) {
try {
return divide(n, d);
} catch (...) {
return std::nullopt;
}
}
constexpr date parse_date(std::string_view input) {
auto [correct, year, month, day] = ctre::match<"([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})">(input);
if (!correct) {
throw incorrect_date{input};
}
return build_date(year, month, day);
}
- Реализована структура данных std: hive для неупорядоченного хранения данных и обеспечения повторного использования памяти, освободившейся после удалённых элементов. Структура оптимизирована для нагрузок с высокой интенсивностью добавления и удаления элементов в произвольном порядке. В отличие от массивов, удаление элемента в
std::hiveне вызывает сдвига других элементов, а приводит к пометке удалённого элемента пустым с последующим заполнением освободившейся позиции при добавлении нового элемента. - Добавлена библиотека std: linalg c API для линейной алгебры, основанный на BLAS.
- Добавлена поддержка механизма синхронизации Hazard pointer, позволяющего без выставления блокировок предотвратить освобождение памяти объектов, с которыми продолжается работа в других потоках. При удалении объекта, он лишь помечается удалённым, но занимаемая объектом память освобождается только когда все потоки снимут hazard-указатель, выставляемый во время работы с объектом.
- Добавлена поддержка механизма синхронизации RCU (open-std.org) («read-copy update») — при операциях записи создаётся новый экземпляр объекта, а операции чтения не блокируются, а продолжают работать со старым экземпляром. После завершения изменения новый экземпляр становится активным и новые операции чтения уже производятся с ним, а старый экземпляр удаляется после завершения читающих его потоков.
- Внесены изменения для усиления безопасности стандартной библиотеки, такие как проверки допустимых значений и выхода за границы буфера. Например, при доступе к элементу
constexpr reference operator[](size_type idx) const;добавляется проверка условияidx < size(). - Предоставлена возможность использования ключевого слова
constexprс разновидностью оператораnew(«placement new») для размещения объекта в заранее выделенной памяти во время компиляции. - Добавлена поддержка структурированных привязок («structured binding») в контексте
constexpr, т. е. ссылки на константные выражения теперь сами могут быть константными выражениями. Поддержка реализована для массивов и простых структур.
constexpr int arr[] = {1, 2};
constexpr auto [x, y] = arr;
- В структурированные привязки добавлена возможность использования синтаксиса
...для указания пакетов (pack), захватывающих оставшееся число элементов из присваиваемой последовательности.
auto [x,y,z] = f(); // в переменные x, y, z будут записаны три элемента, возвращённые f().
auto [...xs] = f(); // в пакет xs будут записаны все элементы, возвращённые f().
auto [x, ...rest] = f(); // В x будет записан первый элемент, а в rest - остальные.
auto [x, y, ...rest] = f(); // В x будет записан первый элемент, в y - второй, а в rest - третий.
auto [x, ...rest, z] = f(); // в x - первый, в rest - второй, в z - третий.
- Добавлена поддержка «тривиальной перемещаемости» типов («trivial relocatability»), позволяющей оптимизировать перемещения объектов заданного типа через их клонирование в памяти без вызова конструкторов или деструкторов. Для классов реализованы свойства
memberwise_trivially_relocatableиmemberwise_replaceable, а для низкоуровневого перемещения одного или нескольких объектов добавлены функцииtrivially_relocate_atиtrivially_relocate. - Реализована поддержка прикрепления функции
main()к глобальному модулю и определения функцииmain()в именованных модулях. - Добавлен вариативный оператор
friend(friend Ts...). - Реализованы атрибуты для структурированных привязок;
- Добавлен синтаксис »= delete («причина»)».
- В базовый набор символов включены »@»,»$» и »`».
- Предоставлена возможность применения структурированного связывания («structured binding») в качестве условия в операторах
ifиswitch. - Добавлена возможность использования сразу нескольких переменных-заполнителей с именем
_в одной области видимости, например, теперь являются корректными конструкции:
struct S {
int _, _;
};
void func() {
int _, _;
}
void other() {
int _; // ранее выводилось предупреждение в режиме -Wunused
}
- Предоставлена возможность использования строковых литералов в контексте, в котором они не используются для инициализации массива символов и не попадают в результирующий код, а применяются только во время компиляции для диагностических сообщений и препроцессинга, например, в качестве параметров директив и атрибутов
Pragma,asm,extern,static_assert,deprecatedиnodiscard. - Добавлены встроенные функции:
__builtin_is_within_lifetimeдля проверки активности альтернативы в объединениях («union») и __builtin_is_virtual_base_of для проверки является ли базовый класс виртуальным. - Реализованы тривиальные бесконечные циклы без неопределенного поведения.
- Обеспечен вывод ошибки при удалении указателя на неполный тип.
- Объявлен устаревшим синтаксис определения вариативных параметров с многоточием без предшествующей запятой (например, когда указывается
void e(int...)вместоvoid e(int, ...)). - Запрещено использование макросов для объявления модулей.
- Переведено в разряд устаревших выполнение неявных преобразований перечисляемых значений в арифметических вычислениях.
int main() {
enum E1 { e };
enum E2 { f };
bool b = e <= 3.7; // устарело
int k = f - e; // устарело
int x = +f - e; // OK
}
- Прекращена поддержка прямого сравнения массивов.
int arr1[5];
int arr2[5];
bool same = arr1 == arr2;
>>> Источник: OpenNET
