LINUX.ORG.RU

В ожидании GCC 12.1

 ,


2

4

GCC - это набор компиляторов языков программирования от GNU.

Релиз GCC 12.1 ожидается в апреле 2022.

GCC 12 уже является системным компилятором Fedora 36. Также GCC 12 доступен в Red Hat Enterprise Linux в Red Hat Developer Toolset (версии 7) или Red Hat GCC Toolset (версии 8 и 9).

В GCC 12

  • улучшили поддержку OpenMP 5.0

  • реализовали поддержку ADA 2022 (флаг -gnat2022)

  • реализовали некоторые возможности следующего стандарта С: C2X (флаг -std=c2x или -std=gnu2x)

  • реализовали часть возможностей С++23.

Более подробное описание реализованного только про новые возможности компилятора С++ без учёта стандартной библиотеки.

В GCC 12 реализовали часть возможностей C++23. Без указания флага стандарта в g++-12 используется -std=gnu++17, чтобы использовать возможности описываемые далее нужно компилировать с флагами -std=c++23 или -std=gnu++23.

Реализованные возможности C++23:

  1. if consteval

Хотя уже в C++20 появились consteval функции, которые могут выполнятся только во время компиляции и был std::is_constant_evaluated (), но была проблема их совместного использования

#include <type_traits>

int slow (int);
consteval int fast (int n) { return n << 1; }

constexpr int fn (int n)
{
  if (std::is_constant_evaluated ())
    return fast (n); // 'n' is not a constant expression
  else
    return slow (n);
}
constexpr int i = fn (10);

https://godbolt.org/z/Yhbqq6K36

P1938R3 представил if consteval который позволяет использовать consteval функции внутри constexpr:

#include <type_traits>

int slow (int);
consteval int fast (int n) { return n << 1; }

constexpr int fn (int n)
{
  if consteval {
    return fast (n); // OK
  } else {
    return slow (n);
  }
}

constexpr int i = fn (10);

https://godbolt.org/z/Kxs6Wjfq6

Заметьте что if consteval требует {} в отличие от обычного if, и что if consteval может быть в обычной не constexpr функции.

  1. auto(x) GCC 12 реализовал P0849 который позволяет auto каст в prvalue
struct A {};
void f(A&);  // #1
void f(A&&); // #2
A& g();

void h()
{
  f(g()); // calls #1
  f(auto(g())); // calls #2 with a temporary object
}

https://godbolt.org/z/x7hn5GKEx

Заметьте что и auto(x) и auto{x} допустимы, хотя decltype(auto)(x) остаётся неверным.

  1. Non-literal переменные в constexpr функциях GCC 12 реализовал P2242R3, который позволяет non-literal переменным, goto, и меткам быть в constexpr функциях если выполнение во время компиляции не доходит до этих мест.
#include <type_traits>

template<typename T> constexpr bool f() {
  if (std::is_constant_evaluated()) {
    return true;
  } else {
    T t; // OK when T=nonliteral in C++23
    return true;
  }
}
struct nonliteral { nonliteral(); };
static_assert(f<nonliteral>());

https://godbolt.org/z/6xnzM46Ej

constexpr int
foo (int i)
{
  if (i == 0)
    return 42;
  static int a;
  thread_local int t;
  goto label;
label:
  return 0;
}

static_assert(foo(0) == 42);

https://godbolt.org/z/PGsErnE4n

  1. Multidimensional subscript operator GCC 12 реализовал P2128R6
struct S {
  int a[64];
  constexpr S () : a {} {};
  constexpr S (int x, int y, int z) : a {x, y, z} {};
  constexpr int &operator[] () { return a[0]; }
  constexpr int &operator[] (int x) { return a[x]; }
  constexpr int &operator[] (int x, long y) { return a[x + y * 8]; }
};

void g ()
{
  S s;
  s[] = 42;
  s[5] = 36;
  s[3, 4] = 72;
}

https://godbolt.org/z/nnGead631

Заметьте что operator[] сейчас не поддерживает аргументов по умолчанию. Рабочая группа рассматривает CWG2507 , и если она примет предложенное решение проблемы, то в будущем такой код будет валиден:

struct X {
  int a[64];
  constexpr int& operator[](int i = 0) { return a[i]; }
};
  1. elifdef и elifndef В С и С++ #ifdef и #ifndef это синтаксический сахар для #if defined(something) и #if !defined(something). Для вариантов с else не было такого синтаксического сахара. Так что его добавили в С++23(и в С2X) и GCC 12: P2334R1
#ifdef __STDC__
/* ... */
#elifndef __cplusplus
#warning "not ISO C"
#else
/* ... */
#endif

https://godbolt.org/z/z4hbj6M7q

  1. Extended init-statement GCC 12 реализовал P2360R0 где расширяются возможности init-statement (в if, for, switch) позволяя им содержать объявление псевдонимов. На практике это означает что теперь валиден подобный код:
for (using T = int; T e : v)
{
    // use e
}

Также можете ознакомиться с описанием исправлений и новыми предупреждениями в GCC 12 в оригинальной статье

>>> Все изменения GCC 12

★★★★★

Проверено: hobbit ()

hobbit вы вроде никогда не подтверждали новости «в ожидании».:( с чего это вдруг?? апрель уже на дворе. выйдет - отрелизите полноценную новость.

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

Ну я тоже сомневался (тем более, что апрель не то, что на дворе, а вот-вот кончится). Но новость не о релизе, она знакомит с новыми возможностями компилятора. Это немного другой поджанр. Поэтому и добавил слова «в ожидании».

Выйдет — сделаем ещё одну.

hobbit ★★★★★ ()
f(auto(g())); // calls #2 with a temporary object

Вот и auto изгадили. Теперь и его использование – ходьба по минному полю с непонятным временем жизни объектов. Горшочек, не вари.

for (using T = int; T e : v)

И снова усложняют язык ради узко-применимых частных случаев. Горшочек, не вари.

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

о чем и речь. обычно вы так не делаете. обычно вы заруливаете: когда выйдет, тогда и познакомимся. я тоже могу сейчас сделать новость «в ожидании след. релиза фрибзд», а 9го мая сделать еще одну.

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

апрель уже на дворе.

Ну да. Но статья вчерашняя: https://developers.redhat.com/articles/2022/04/25/new-c-features-gcc-12

и они пишут

Version 12.1 of the GNU Compiler Collection (GCC) is expected to be released in April 2022.

Так что возможно уже на днях выпустят.

Хотя возможно мне стоило написать «Не подтверждать до релиза».

Извиняюсь :(

fsb4000 ★★★★★ ()

C++ как слои земной коры. С каждым стандартом добавляются новые и новые фичи. Они накладываются на старые. Старые фичи затвердевают и окаменевают под жирным слоем новых. А потом начинает накладываться следующий слой.

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

Извиняюсь :(

да ладно! это просто ревность у меня взыграла!

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

Откинем пока вычисление в компилтайме, и посмотрим на предлагаемый код.

Я не понимаю, что призван продемонстрировать этот пример:

struct X {
  int a[64];
  constexpr int& operator[](int i = 0) { return a[i]; }
};

То, что интерфейс получения значения массива можно делать и через поле структуры и обращаясь к самой структуре?
X x;
int i=x.a[5];
int j=x[5];

? Но зачем такое нужно? А если в объекте два поля, то тогда как?

Может быть в этом загадочном коде неявно скрыта проверка выхода за границы массива, ведь это вечная проблема C/C++? Но об этом речь тоже не идет.

Что это, для чего это?

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

пункт 2 оффтопик листа нарушаем-с?.. зачем это здесь?..

Sahas ★★★★★ ()

Выучи русский язык уже, неуч. Это же невозможно читать.

реализовали
реализовали
реализовали
реализованного
реализовали
Реализованные

Других слов совсем не знаешь?

Заметьте что

Ты серьёзно? Ничего не смутило?

чтобы использовать возможности описываемые далее нужно компилировать

Может, не стоило бросать школу?

Удалите это позорище.

skvitek ★★ ()
Последнее исправление: skvitek (всего исправлений: 6)

И чё - до релиза недотерпели? Откуда вдруг внезапное новостное недержание?

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

Так может быть, ты хотел показать конструкцию:

int j=x[5];

Доступ к полю структуры int i=x.a[5] это же базовая возможность языка.

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

тут показывается, что теперь можно писать

auto i = x[];

и это будет тоже самое, что если бы ты написал

auto i = x[0];

Раньше нельзя было задать значение по умолчанию для оператора []

SR_team ★★★★★ ()

Меня в новостях про компиляторы больше привлекают всякие фокусы с новыми оптимизациями и поддержкой новых процессоров. Так, например, мне не понятно, появилась ли поддержка будущих Ryzen 7000?

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

C++ как слои земной коры. С каждым стандартом добавляются новые и новые фичи. Они накладываются на старые. Старые фичи затвердевают и окаменевают под жирным слоем новых. А потом начинает накладываться следующий слой.

Если бы русский язык развивался как C++, наш алфавит бы состоял минимум из семидесяти символов: Аз, Буки, Веди,.. Ё (самая свежая буква)
А какие бы были тексты, я даже боюсь представить...

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

Crocodoom ★★★★★ ()

реализовали поддержку ADA 2022

вот ведь! жив полутруп, и даже конференции продолжаются

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

Раньше нельзя было задать значение по умолчанию для оператора []

По ссылке на обсуждение именно это и сказано. Но сам пример, по-моему, какой-то вообще марсианский приведен.

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

нормальный пример, в нем приведена минимальная структура и оператор [] с аргументом по умолчанию

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

Multidimensional subscript operator
Не прошло и 30-и лет...

struct S {
  int a[64];
  constexpr int &operator[] (int x, long y) { return a[x + y * 8]; }
};

S s;
s[3, 4] = 72;


Значит ли это, что теперь можно проще пользоваться многомерными массивами как в Фортране, без всей этой дичи с указателями на указатели ** и двойным/многоным разыменовыванием?

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

Это не минорная версия, а первый релиз 12 ветки. Каждый год выходит GCC N.1, а GCC (N + 1).0 – это будущая версия. Т.е. если собрать мастер ветку, то получится GCC 13.0, что изменится на GCC 14.0 около января (они вроде с зимы начинают готовить релиз).

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

consteval функции, которые могут выполнятся только во время компиляции

Помню хипстеры бегали и рекламировали constexpr как средство для выполнения кода во время компиляции. Но видать не осилили и пришлось делать «мамой клянусь на этот раз точно-точно для выполнения во время компиляции» под названием consteval.

for (using T = int; T e : v)

for (auto& e : v) не? Какие реальные юзкейсы у этой предъявы?


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

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

Теперь и его использование – ходьба по минному полю с непонятным временем жизни объектов.

Нет, теперь это полностью консистентно с

f(T(g()));

но выводит тип автоматически и не требует дополнительных изощрений для корректной обработки prvalue-значений.

И снова усложняют язык ради узко-применимых частных случаев

Нет, это фиксит недоработку, благодаря которым это работало для typedef, но не работало для using. При этом работа для typedef полностью естественна как с точки зрения грамматики, так и в целом с точки зрения семантики расширенной инициализации.

В свою очередь расширенная инициализация также улучшает консистентность: for уже десятилетия имеет возможность проинициализировать счетчик, а ranged-for, if и while – нет, хотя никаких причин для этого нет, более того, ее использование позволяет не замусоривать внешний скоуп.

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

auto(g()) делает копию результата g(), какого бы типа ссылки он не был (из T& сделает временный объект типа T). Я так понял.

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

Помню хипстеры бегали и рекламировали constexpr как средство для выполнения кода во время компиляции. Но видать не осилили и пришлось делать «мамой клянусь на этот раз точно-точно для выполнения во время компиляции» под названием consteval.

constexpr и consteval полностью ортогональны друг другу.

См. нить начиная с Долгожданная статья ученика Столярова о том, что rust-говно (комментарий)

Какие реальные юзкейсы у этой предъявы?

Вкратце: просто бОльшая консистентность, см. выше. Подробнее см. ссылку на paper, в тексте новости есть.

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

Значит ли это, что теперь можно проще пользоваться многомерными массивами как в Фортране, без всей этой дичи с указателями на указатели ** и двойным/многоным разыменовыванием?

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

Для стандартной библиотеки есть два предложения, но они пока обсуждаются: mdspan и mdarray

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

Обосновать можно что угодно, даже динамическую типизацию. Что не отменяет. В случае if (init; cond) – правильно было бы сделать полноценное statement expression как в ФП, а не костыли с одним единственным initialization statement.

Т.е. по-хорошему надо чтобы внутрь условия if можно было бы запихать произвольный блок кода. Хорош или плох синтаксис в gcc по ссылке выше – в данном случае вторично.

pr849 ()
Ответ на: комментарий от Crocodoom

Если бы русский язык развивался Ё

То придумали бы для этого звука свой символ, и всякие не писали бы Е вместо неё, да и безударное о в а уже пофиксили бы, или что-то между для письма предоставили.

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

Т.е. по-хорошему надо чтобы внутрь условия if можно было бы запихать произвольный блок кода.

if (auto [x, y, z] = [&]{
    auto x = foo();
    auto y = bar(x);

    return std::tuple{ x, y, baz(x, y) };
}(); z) {
   // ...
}

не говоря уже о возможности завернуть весь if в свой скоуп.

что не отменяет

Я не буду повторяться и заново рассказывать о том, почему это нужно – rationale более чем подробно описывает различные юзкейсы. Просто предлагаю автору родить то же самое на CRTP и сравнить понятность и простоту кода.

Бонусные очки за воспроизведение полиморфности по value category this.

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

Этот паттерн использования анонимной функции – тоже костыль. Между лямбдой и expression statement я выберу последнее.

не говоря уже о возможности завернуть весь if в свой скоуп.

Именно. Но ты же выше писал: «ее использование позволяет не замусоривать внешний скоуп.» Путаешься в показаниях.

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

Путаешься в показаниях.

Ни в коем случае. Я не утверждал, что это единственный способ изолировать скоуп if от внешнего, но ради 1-2 переменных оборачивать if в скоуп никто не будет – а обычно задействуется именно 1-2 переменных. Миллионы for с единственной i не дадут соврать. При этом добавляется все уже сказанное про консистентность.

Между лямбдой и expression statement я выберу последнее.

Expression statement сыплются на таких примерах как early return и return из внешнего скоупа. Да, их удобно иметь. Нет, они не стоят изменений в языке и проблем, связанных с их особенностями.

Этот паттерн использования анонимной функции – тоже костыль

Нет, это один из изначально задекларированных способов использования лямбд. Works as intended.

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

костыль

Нет, это один из изначально задекларированных способов использования лямбд.

Одно другому не мешает. :-/ Печально, что костыли изначально декларируются там, где можно было сразу сделать нормально. Потому что функционально этот способ экивалентен expression statement, но expression statement – это тривиальная конструкция в духе ФП «всё – выражение», а лямбда – лишняя сущность на ровном месте, причём ещё и временный объект. А что в итоге он optimized out – во-первых пофиг, а во-вторых получается что это уже не одна, а две лишних единицы информации: что это временный объект, и что он optimized out.

Я именно потому считаю это костылями, что подход «всё – выражение» проще, красивее, выразительнее, универсальнее, понятнее с точки зрения знакомых с ФП, и включает эти костыли как частный случай. Вместо частных случаев могли бы и поуниверсальней чего забабахать. Даже такую ерунду и то задизайнили наполовину: вместо if (int a = f(); int b = g(); ...; a == b) надо писать if (auto [a, b, ...] = std::tuple{f(), g(), ...}; a == b). Идиотизм же. Туда-сюда временный тупл на ровном месте.

А могли бы вообще if {expression statement без обвязки} .... Пока ещё своими костылями вообще все возможности впихнуть в этот многострадальный синтаксис что-то полезное не исчерпали.

Нет, они не стоят изменений в языке

Почему нет? В gcc же сделали.

и проблем, связанных с их особенностями.

Каких проблем? Мне не встречались. Бесит только нагромождение скобок ({ ... }) и что нельзя отключить индивидуально warning при включённом pedantic.

pr849 ()
Последнее исправление: pr849 (всего исправлений: 5)
Ответ на: комментарий от Siborgium

Expression statement сыплются на таких примерах как early return и return из внешнего скоупа.

Проглядел спросонья. В первом кейсе я тоже юзаю лямбду. А про второй не понял.

pr849 ()

которые могут выполнятся

tsya.ru и чемодан запятых.

Radjah ★★★★★ ()

ну как бы не очень то и нужно

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

Второй – это больше относится к ФП, а точнее к Rust. Там в expression’ах return относится именно к expression, а не к функции, в котором оно находится, что не позволяет из expression сделать return из всей функции.

В gcc выбрали другую семантику – и отвалился early return. При этом оба варианта имеют полное право на жизнь. Внесение в стандарт только одного варианта повлечет за собой недовольство предпочитающих иной вариант.

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