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:
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
функции.
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) остаётся неверным.
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
- 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]; }
};
- 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
- Extended init-statement
GCC 12 реализовал P2360R0 где расширяются возможности init-statement (в
if
, for
, switch
) позволяя им содержать объявление псевдонимов. На практике это означает что теперь валиден подобный код:
for (using T = int; T e : v)
{
// use e
}
Также можете ознакомиться с описанием исправлений и новыми предупреждениями в GCC 12 в оригинальной статье
>>> Все изменения GCC 12