07.06.2023

В ожидании GCC 12.1

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

Источник.