LINUX.ORG.RU

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

 ,


2

7

Комитет 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<float> a = {1.0f, 2.0f, 3.0f, 4.0f};
        std::simd<float> 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<unsigned> 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

★★★★★

Проверено: Dimez ()
Последнее исправление: dataman (всего исправлений: 1)

Интересно, кто-нибудь из комитета C++ ушёл оттуда по причине тяжелых психиатрических проблем?

seiken ★★★★★
()

Добавлена поддержка рефлексии

А вот и дорогу к Spring проложили. Недавно как раз интересовались.

kaldeon ★☆
()

Как кто-то верно заметил ещё про какую-то предыдущую версию, “Now we can say that rocket science is not building a C++ compiler.”

shdown
()
Ответ на: комментарий от kaldeon

А вот и дорогу к Spring проложили. Недавно как раз интересовались.

Добавлена поддержка рефлексии (Reflection), позволяющей отслеживать и модифицировать элементы программы на стадии компиляции.

А я всегда думал, Spring использует какой-то декомпилятор *.class файлов в рантайме при старте главного спринговского класса, типа, шарит в classpath на предмет классов «из моего пакета» или что-то типа того.

seiken ★★★★★
()
Ответ на: комментарий от seiken

Всё верно, в джаве рантайм-рефлексия, а в плюсах будет на этапе компиляции. Не знаю в чём проявится различие на практике, кроме большей скорости и меньшей гибкости.

kaldeon ★☆
()
Последнее исправление: kaldeon (всего исправлений: 5)

Чет вспомнилось. Только заменить аду на плюсы.

Настоящие Прогpаммисты считают язык ADA бесспорной эстетической ценностью, но не торопятся прогpaммировать на нем, потому что громоздкость этого языка затрудняет его реализацию. Впрочем, многие программисты этого не замечают - они продолжают спорить о том, что еще стоит добавить в ADA.

liksys ★★★★
()
Последнее исправление: liksys (всего исправлений: 1)
Ответ на: комментарий от seiken

Что значит «ушёл»? Они туда поэтому и пришли!

GAMer ★★★★★
()
Ответ на: комментарий от Skullnet

К тому времени как С++26 станет минимальной версией для Qt, т.е. году так к 2040

Begemoth ★★★★★
()

Вносите царя, какие нововведения являются самыми полезными и нужными? Почитал, как то без этого и раньше не страдал, ну да чето полезно, но не шибко

I-Love-Microsoft ★★★★★
()

Жуть какая. Может стоит туда привлечь мамкиных любителей синтаксического сахара, аля - Kotlin? Хотя… Какая разница? - лучше они сделать не смогут, ибо нативной компиляции там - в Kotlin - нет.

TechnoMag ★★★
()
Последнее исправление: TechnoMag (всего исправлений: 2)
Ответ на: комментарий от seiken

Мне кажется, конечная цель людей, развивающих C++, состоит в том, чтобы сделать язык максимально далёким и от английского и от языка математики. В конечном итоге, строка случайных символов будет синтаксически верной программой не только для Perl, но и для C++. Я после чтения кода на C++ отдыхаю, читая текст на китайском. Он куда понятнее.

scanner
()
Ответ на: комментарий от Skullnet

Должен C++29 выйти и потом лет пять пройти. К 2035 году

Reset ★★★★★
()

Прекращена поддержка прямого сравнения массивов.

Традиционный вопрос: кому мешало?

hobbit ★★★★★
()
Ответ на: комментарий от hobbit

Традиционный вопрос: кому мешало?

С++ ругают за раздутость, так что, чтобы добавить что-то ненужное, надо сначала убрать что-то нужное.

squareroot ★★★★
()

Ужоснах. Они ещё на раст чёто хрюкоют.

yvv1
()
Ответ на: комментарий от Skullnet

Когда можно будет уже выкинуть MOC-компилятор из Qt.

Когда LOR процитирует новость OpenNET об этом. :)

Или фич для этого в C++ ещё недостаточно?

Я не знаю Qt, но #embed можно уже достаточно давно использовать.

dataman ★★★★★
() автор топика

В базовый набор символов включены «@», «$» и «`».

Но для рефлекии всё равно сделаем уродливые «^^» и оператор бояна «[::]».

thunar ★★★★★
()

Пишу в эпичном треде
Кстати, предлагаю игру - накатывать при каждом упоминани Ржавого

Myp3ik ★★★
()
Ответ на: комментарий от dataman

но #embed можно уже достаточно давно использовать

Вроде только с указанием ключей экспериментальных компилятору и то не каждому. Я прошлым летом страдал без #embed, очень мне хотелось json-описания в бинарник вставлять без костылей.

Loki13 ★★★★★
()
Последнее исправление: Loki13 (всего исправлений: 1)
Ответ на: комментарий от Loki13

Вроде только с указанием ключей экспериментальных компилятору и то не каждому.

g++ 15.2.0 не ругается даже с -std=c++11, clang-22 выдаёт предупреждение warning: #embed is a Clang extension [-Wc23-extensions].

dataman ★★★★★
() автор топика

В базовый набор символов включены «@», «$» и «`».

Перешёл по ссылке но так и не понял, куда именно их добавили. Их теперь можно в именах переменных итд использовать? gcc на $ и так вроде не ругается (но ругается as если этот символ до него доберётся).

firkax ★★★★★
()
Ответ на: комментарий от thunar

По идее ^^ должно быть для логического xor, то есть a^^b то же самое что (!a)!=(!b).

firkax ★★★★★
()

Аксиомы и концерты есть? Если нет, то не нужно.

buddhist ★★★★★
()
Ответ на: комментарий от liksys

Ну вот про Аду все еще спорят, а PL/1 умер после того, как официальное описание языка от IBM разрослась более чем на 1000 страниц, и на очередном съезде PL/1 User Group подняли вопрос о том, что пользователям не хватает каких-то фич.

gns ★★★★★
()

Утверждается, что Страуструпп вдохновлялся Барбарой Лисков и ее языком CLU (см старую книжку «Использование абстракций и спецификаций при разработке программ»).

Ивот;


int f(const int x)
          pre (x != 1) // требования ко входным данным
          post (r : r == x && r != 2) // требования к результату; r - значение с результатом
       {
          contract_assert (x != 3);
          return x;
       }

Что есть CLUшные

requires
modifies
effects

Ну и Эффелёвые немного (ЕМНП, конечно) :)

gns ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Навскидку template for выглядит полезной штукой. Копипасты меньше будет.

gns ★★★★★
()
static_assert(^^i != ^^j);

— Что бы нам ещё воткнуть в язык? Этот комбайн разве что кофе не варит.

— А давайте вставим в язык смайлики!

scanner
()

Поддерживающие C++26 стандартные библиотеки реализованы в рамках проекта Boost.

Павуки-крестовики могут объяснить, нашиша они вот так делают? Запилить в настоящей стандартной библиотеке ну совсем не вариант?

Bfgeshka ★★★★★
()
Ответ на: комментарий от Bfgeshka

не вариант, стандартных библиотек много, когда-нибудь они подтянутся

Reset ★★★★★
()
Ответ на: комментарий от scanner

Я после чтения кода на C++ отдыхаю, читая текст на китайском. Он куда понятнее.

Нет ) Код на плюсах хотя бы однозначен. А эти закорючки, каждая толкуемая десятком способов, могут сложится чёрт знает во что. Хотя, если дальше дуолинго не отходить от путунхуа, да сравнить с легаси-кодом лет хотя бы десяти… Ну, может быть.

JaneDoe
()

Спасибо за новость. Завёл себе таску: к 2030 году посмотреть, что они там наговнякали в своих комитетах. Раньше вряд ли понадобится.

JaneDoe
()

#embed, std::simd, std::linalg, std::inplace_vector прямо хорошо. Контракты нужно понять, но вроде как тоже хорошо. Баян ([:...:])… у меня две претензии к Rust, одну из них Комитет старательно сводит на нет. Остальное больше хорошо, чем нет. template for подумать упороться…

А вот библиотеки для корутин и сети я так и не вижу. Standalone Asio forever!

hatred ★★★★
()
Ответ на: комментарий от Skullnet

Там много рантайм обмазок. Скорее всего ещё не скоро.

hatred ★★★★
()
Ответ на: комментарий от hobbit

Это никогда не было сравнением массивов. Массив вырождался в указатель и сравнивались именно указатели. Грубо: всегда был false. Я могу в деталях ошибаться, пусть более сведущие меня поправят, но:

тогда как для std::vector/std::array эта семантика работает:

hatred ★★★★
()
Ответ на: комментарий от dataman

#embed можно уже достаточно давно использовать.

не в курсе, насколько переносимо между компиляторами до C++26?

hatred ★★★★
()
Ответ на: комментарий от thunar

Но для рефлекии всё равно сделаем уродливые «^^» и оператор бояна «[::]».

Да, брат, это фиаско («полный провал, 6 букв, вторая ‘и’»)

hatred ★★★★
()

Эх, а я ещё предыдущие не до конца изучил… Впрочем, как и все :)

pihter ★★★★★
()

эту стюардессу уже не закопают

культ С++ на долгие века

qulinxao3 ★☆
()
Ответ на: комментарий от Reset

ах разве комитет законтрактовал такой assert на себя ?

qulinxao3 ★☆
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.