IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

GCC 12 apportera de nouvelles fonctionnalités C++, des améliorations et les corrections de bogues,
Annoncée pour avril 2022

Le , par Bruno

163PARTAGES

7  0 
La version 12.1 de la collection de compilateurs GNU (GCC) devrait être publiée en avril 2022. Comme chaque version majeure de GCC, cette version apportera de nombreux ajouts, améliorations, corrections de bogues et nouvelles fonctionnalités. GCC 12 est déjà le compilateur système de Fedora 36. GCC 12 sera également disponible sur Red Hat Enterprise Linux dans le Red Hat Developer Toolset (version 7) ou le Red Hat GCC Toolset (version 8 et 9).

Plusieurs propositions ont été implémentées dans GCC 12. Le dialecte par défaut dans GCC 12 est -std=gnu++17 ; pour activer les fonctionnalités C++23, les options de ligne de commande -std=c++23 ou -std=gnu++23 doivent être utilisées. (Cette dernière option autorise les extensions GNU). Voici, ci-dessous, les nouvelles fonctionnalités affectant le C++ :


Un certain nombre de constructions auparavant interdites sont maintenant autorisées, et certaines de ces caractéristiques peuvent potentiellement réduire la taille des programmes.

if consteval

C++17 a introduit l'instruction if constexpr. La condition dans if constexpr doit être une expression constante (elle est manifestement évaluée constante). Si la condition est évaluée à true, la branche else, si elle est présente, est écartée. Cela signifie que la branche else n'est pas du tout instanciée pendant la compilation, ce qui est un comportement différent d'un if ordinaire. Si la condition est évaluée à false, la branche true est également rejetée.

Si une fonction est déclarée constexpr, elle peut être évaluée ou non au moment de la compilation, en fonction du contexte. Pour offrir au programmeur une certaine visibilité sur le moment où la fonction est évaluée à la compilation, C++20 a introduit une nouvelle fonction de bibliothèque, std::is_constant_evaluated(), qui renvoie true si le contexte actuel est évalué à la compilation :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <type_traits>

int slow (int);

constexpr int fn (int n)
{
  if (std::is_constant_evaluated ())
    return n << 1; // #1
  else
    return slow (n); // #2
}

constexpr int i = fn (10); // does #1
int n = 10;
int i2 = fn (n); // calls slow function #2

C++20 a introduit le mot-clé consteval. Une fonction (éventuellement membre) ou un constructeur marqué comme consteval est une fonction immédiate. Les fonctions immédiates sont évaluées pendant la compilation et doivent produire une constante, sauf si l'appel à une fonction immédiate a lieu dans une autre fonction immédiate ; si ce n'est pas le cas, le compilateur produit une erreur. Le compilateur n'émet pas de code réel pour ces fonctions. Cependant, les règles du langage ne permettent pas au développeur de remplacer n << 1 dans le test précédent par un appel à une fonction consteval :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
#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);

Pour résoudre ce problème, la proposition P1938R3 a introduit if consteval, que GCC 12 met en œuvre. if consteval permet au développeur d'invoquer des fonctions immédiates, comme illustré ici :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#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);

Notons qu'il est valide d'avoir if consteval dans une fonction ordinaire, non-constexpr. Notons également que if consteval nécessite { }, contrairement à l'instruction if ordinaire. Il y a un problème avec l'interaction entre if constexpr et std::is_constant_evaluated(), mais heureusement le compilateur peut détecter ce problème. La solution est examinée dans la section suivante Extended std::is_constant_evaluated in if warning.

auto(x)

GCC 12 implémente la proposition P0849, qui autorise auto dans un cast de style fonction, dont le résultat est une pure rvalue (prvalue) :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
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
}

Notons que auto(x) et auto{x} sont tous deux acceptés ; cependant, decltype(auto)(x) reste invalide.

Variables non-littérales dans les fonctions constexpr

GCC 12 implémente la proposition C++23 P2242R3, qui autorise les variables non littérales, les gotos et les labels dans les fonctions constexpr tant qu'ils ne sont pas évalués de manière constante. Ce comportement étendu est utile pour du code comme le suivant (extrait de la proposition) :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
#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>());

Cet exemple ne compile pas en C++20, mais il compile en C++23 car la branche else n'est pas évaluée. L'exemple suivant ne compile également qu'en C++23 :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
constexpr int
foo (int i)
{
  if (i == 0)
    return 42;
  static int a;
  thread_local int t;
  goto label;
label:
  return 0;
}

Opérateur d'indice multidimensionnel

GCC 12 supporte la proposition C++23 P2128R6, un opérateur d'indice multidimensionnel. Les virgules dans les expressions d'indices ont été dépréciées dans C++20 via la proposition P1161R3, et dans C++23 la virgule dans [ ] a changé de signification.

Le C++ utilise l'opérateur membre operator[] pour accéder aux éléments d'un tableau, ainsi qu'aux types de type tableau tels que std::array, std::span, std::vector et std::string. Toutefois, cet opérateur n'acceptait pas d'arguments multiples en C++20, de sorte que l'accès aux éléments des tableaux multidimensionnels était implémenté à l'aide d'opérateurs parenthèses d'appel de fonction tels que arr(x, y, z), et d'autres solutions de contournement similaires. Ces solutions de contournement présentent un certain nombre d'inconvénients. Pour atténuer les problèmes liés à leur utilisation, C++23 permet à l'opérateur [] de prendre zéro ou plusieurs arguments.

En conséquence, ce scénario de test est accepté avec -std=c++23 :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
template <typename... T>
struct W {
  constexpr auto operator[](T&&...);
};

W<> w1;
W<int> w2;
W<int, int> w3;

Voici ce qui pourrait être un exemple plus clair, avec une...
La fin de cet article est réservée aux abonnés. Soutenez le Club Developpez.com en prenant un abonnement pour que nous puissions continuer à vous proposer des publications.

Une erreur dans cette actualité ? Signalez-nous-la !