Évolution de C++ : petite revue des fonctionnalités existantes du langage qui ont été supprimées de C++ 17
Et celles qui ont été ajoutées

Le , par Stéphane le calme, Chroniqueur Actualités
C ++ 17 est la version la plus récente du langage de programmation C ++ révisé par la norme ISO / IEC 14882. Sa spécification a atteint l'étape DIS (Draft International Standard) en mars 2017 et après approbation, la norme finale a été publiée en décembre 2017. Des centaines de propositions ont été avancées pour la mise à jour des fonctionnalités de C ++ 17.

Passons donc en revue quelques-unes des nouvelles fonctionnalités du langage ainsi que les fonctionnalités existantes supprimées de C ++.

Fonctions C ++ existantes qui ont été supprimées

Suppression des trigraphes

Le jeu de caractères utilisé par le langage C++ comprend toutes les lettres en majuscules et en minuscules, tous les chiffres et les caractères suivants : . , ; : ! ? " ' + - ^ * % = & | ~ _ # / \ { } [ ] () < >

Malheureusement, certains environnements sont incapables de gérer quelques-uns de ces caractères. C'est pour résoudre ce problème que les trigraphes ont été créés.

En clair, les trigraphes sont des séquences de trois caractères commençant par deux points d'interrogation. Ils permettent de remplacer les caractères qui ne sont pas accessibles sur tous les environnements. Par exemple :
  • ??= génère #
  • ??- génère ~
  • ??< génère {

Il est important de mentionner que tous les jeux de caractères source de C ++ sont compatibles avec l'ASCII 7 bits. Vous n'utiliserez donc sans doute jamais les trigraphes, à moins d'y être forcé. C’est ce point (la rareté d’utilisation) qui fait en sorte que dans la nouvelle version les trigraphes ne sont plus utilisés.

La suppression de ces séquences rendra la phase de traduction plus simple.

Suppression de “register”

Le mot clé "register", qui sert à déclarer les variables registre, a été déprécié dans la norme C ++ 11. Cette fois-ci, en C ++ 17, il a été supprimé. Il faut cependant noter que ce mot clé est toujours réservé et peut être réutilisé dans les futures révisions.

Suppression de l'opérateur obsolète ++

Les expressions post-préfixe et préfixe (++) ne sont plus valables pour les opérandes booléens.

Suppression des spécifications d'exception obsolètes

En C ++ 17, la spécification d'exception fait partie du système de type. Mais la norme comporte toujours une spécification d'exception ancienne et obsolète, qui ne semble pas être pratique et utilisée.

Par exemple:

Code C++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
void fooThrowsInteger(int x) throw(int) 
{   
   printf_s("throw int\n");   
  
if (x == 0) 
   { 
      throw 1;   
   } 
}
La portion de code mentionné ci-dessus est obsolète depuis 2011. Seule la méthode "throw ()" reste comme synonyme de "noexcept ()" depuis C ++ 11.

Suppression de auto_ptr

Le C ++ 11 nous fournit des pointeurs intelligents comme shared_ptr, weak_ptr et unique_ptr. En comparaison, auto_ptr, qui est plus ancien, s’est avéré bogué et a donc été considéré comme étant obsolète en C ++ 11. Dès lors, la suppression de C ++ 17 paraissait inévitable.

Presque toutes les fonctionnalités qui ont été abandonnées en C ++ 11 et remplacées par des composants plus récents ont été supprimées, bien que leurs noms soient toujours réservés.


Quelques nouveautés apportées par C++ 17

Spécifications d'exception

Dans les versions précédentes de C ++, les spécifications d'exception pour une fonction n'étaient pas associées au type de fonction. Dans ce cas, nous avons rencontré une erreur comme suit :

Code C++ : Sélectionner tout
1
2
3
4
5
6
void (*t)(); 
void (**tt)() noexcept=&t; // error: can-not convert to 
                     	// pointer to noexcept 
  
struct V { typedef void (*t)(); operator t(); }; 
void (*k)() noexcept = V(); // error: can-not convert to pointer to noexcept

Mais maintenant, dans C ++ 17, la spécification d'exception est une partie de type système. Une des raisons importantes pour l'ajout de cette fonctionnalité est une possibilité de permettre une meilleure optimisation. En clair, vous pouvez utiliser le spécificateur "noexcept" pour déclarer qu'une fonction peut lancer quelque chose ou non.

Règles auto pour une initialisation directe de liste

Vous pouvez maintenant déclarer un paramètre de modèle non-type avec un espace réservé de type auto. En C ++ 11, nous sommes confrontés à ce problème étrange où auto x {1}; est déduit comme initializer_list. Ce problème est résolu dans la nouvelle norme, donc il sera déduit comme int.

Avant de continuer, il faut comprendre les deux méthodes d'initialisation de liste que sont l’initialisation par copie et l’initialisation directe.

Code C++ : Sélectionner tout
1
2
auto a = foo(); // this is copy initialization 
auto a{foo};    // this is direct initialization, it initializes an initializer_list

Pour une initialisation directe, C++ 17 introduit de nouvelles règles:
  • pour une liste avec un seul élément, l'autodéduction déduira de cette entrée particulière ;
  • pour une liste avec plusieurs éléments, l'autodéduction va générer une erreur.

Code C++ : Sélectionner tout
1
2
3
4
5
auto a1 = { 21, 12 };  // decltype(a1) is std::initializer_list<int> 
auto a3{ 11, 3 };      // error: not a single element 
auto a2 = { 11, 3.0 }; // error: cannot deduce element type 
auto a4 = { 7 };       // decltype(a4) is std::initializer_list<int> 
auto a5{ 8 };          // decltype(a5) is int

Static_assert sans message

Cette fonctionnalité mise à jour permet d'avoir une condition sans passer le message, ou vous pouvez dire que la déclaration static_assert ne nécessite plus de second argument. La version avec message est également disponible. Elle est compatible avec d'autres assertions telles que BOOST_STATIC_ASSERT.

Code C++ : Sélectionner tout
1
2
static_assert(std::is_arithmetic_x<A>, "A should be arithmetic"); 
static_assert(std::is_arithmetic_x<A>); // no such message required in C++17

Conclusion

Bien entendu, cette liste est très loin d'être exhaustive ; le nombre de spécifications apportées par C++ 17 (1586 contre 1368 pour C++14) est un assez bon indicateur pour le rappeler. Les nouveautés s'imbriquent dans diverses catégories allant des changements dans la bibliothèque aux clarifications du langage.

Source : MycPlus

Et vous ?

Quelles sont les nouveautés apportées par C++17 qui vous intéressent le plus ?

Voir aussi :

Quels sont les EDI C/C++ les plus utilisés en 2018 ? Un développeur nous livre les résultats de son étude
Pourquoi les langages C et C++ auraient-ils encore de nombreuses années devant eux ? Donnez votre avis


Vous avez aimé cette actualité ? Alors partagez-la avec vos amis en cliquant sur les boutons ci-dessous :


 Poster une réponse Signaler un problème

Avatar de Bktero Bktero - Modérateur https://www.developpez.com
le 09/04/2018 à 14:42
La liste complète peut être trouvée ici : https://isocpp.org/files/papers/p0636r0.html
Avatar de camboui camboui - Membre éclairé https://www.developpez.com
le 10/04/2018 à 10:24
J'adore, je suis fan !
J'en redemande avec C++20 même si je me noie dans les multiples syntaxes d'instanciation d'objets pour lesquels le code machine généré reste finalement le même (cf copy initialization, direct initialization, etc)

Je ne m’ennuierai jamais jusqu'à mon dernier souffle
Malgré quelques petits soucis ça et là, par exemple avec constexpr que je pensais pouvoir utiliser bien souvent en remplacement de const, exemple:
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct RecColumnInfo
{
    long sortable;
    long seqnbr;
    char Name[80];
};

const RecColumnInfo gColumnInfo[]=
{
/*   0 */   { 0,    1000,   "Organization ID"},
/*   1 */   { 0,    1001,   "Position ID"},
/*   2 */   { 0,    1002,   "Person ID"},
...
};
En mettant un constexpr à la place du const ligne 9 le prg n'avait plus le comportement attendu... (mais je n'ai pas creusé pourquoi, on ne touche pas à un code qui fonctionne...)
Avatar de koala01 koala01 - Expert éminent sénior https://www.developpez.com
le 10/04/2018 à 11:49
Citation Envoyé par camboui  Voir le message
En mettant un constexpr à la place du const ligne 9 le prg n'avait plus le comportement attendu... (mais je n'ai pas creusé pourquoi, on ne touche pas à un code qui fonctionne...)

Et en déclarant ton tableau static constexpr
PS: au passage: pourquoi long pour sortable un bool ne serait pas mieux adapté, vu que tu n'as dans tous les cas que deux solutions ou bien est-ce pour éviter les différences d'alignement qui pourraient survenir sur différentes architectures / système
Dans cette dernière éventualité, tu aurait alors meilleurs temps de prendre un type à taille définie, comme /*u*/int_8t.
PPS: pourquoi [c]char[80] pour Name
PPPS: Un peut d'homogénéité dans tes conventions de nommage ne serait pas superflue
Avatar de wolinn wolinn - Membre éclairé https://www.developpez.com
le 10/04/2018 à 12:30
Citation Envoyé par Stéphane le calme Voir le message

...
Quelles sont les nouveautés apportées par C++17 qui vous intéressent le plus ?
Le langage lui-même était déjà bien assez riche et puissant pour mes besoins, mon intérêt pour C++ 17 porte surtout sur les progrès de la STL qui va avec, en particulier sur le parallélisme.
Avatar de Bktero Bktero - Modérateur https://www.developpez.com
le 10/04/2018 à 14:29
Citation Envoyé par Stéphane le calme Voir le message
Quelles sont les nouveautés apportées par C++17 qui vous intéressent le plus ?
Mince j'ai même pas répondu à la question !

On a commencé en décembre un nouveau projet et on est parti sur du C++17, en se disant qu'on trouverait bien des trucs cools à utiliser dans tout ça. Il y a déjà 2 trucs trop bien et un truc bien que j'ai utilisé dans mon code :
  1. if constexpr : j'utilise ça dans une classe template de calcul en virgule fixe pour faire des choix en fonction des paramètres fournis.
  2. __has_include("" : dans cette même classe, je teste si un fichier existe. Si oui, je l'inclus, sinon j'inclus un fichier par défaut. Ça sert pour que les utilisateurs de la bibliothèque puisse fournir leur version spécialisée d'un fichier dont je fournis une version standard.
  3. [[maybe_unused]] : fini les cast du genre (void) variable_qui_ne_sert_pas_en_fait, par exemple pour implémenter des fonctions de callback de l'OS.


Et je viens de découvrir les fold expressions et j'ai déjà vu un code qui aurait été mieux avec
Avatar de Bousk Bousk - Rédacteur/Modérateur https://www.developpez.com
le 10/04/2018 à 15:58
Mon quarté gagnant
- if constexpr
- string_view
- constexpr lambda
- if(init; condition)

D'autres gadgets comme les namespace inline comme namespace My::Name::Space
Je suis encore un peu dubitatif sur std::byte par contre

Malheureusement on reste sur C++14 pour l'instant sans prévision de passer à C++17
Avatar de Pyramidev Pyramidev - Membre expert https://www.developpez.com
le 10/04/2018 à 19:00
Citation Envoyé par Stéphane le calme Voir le message
Quelles sont les nouveautés apportées par C++17 qui vous intéressent le plus ?
Pour ma part :
  • les nombreux ajouts dans la bibiothèque standard (ex : std::filesystem, std::optional, std::string_view, std::invoke, std::variant, std::apply...) ;
  • if constexpr ;
  • les structured bindings ;
  • la déduction des arguments de template en appelant un constructeur.


Citation Envoyé par Bktero Voir le message
[[maybe_unused]] : fini les cast du genre (void) variable_qui_ne_sert_pas_en_fait, par exemple pour implémenter des fonctions de callback de l'OS.
Dans ce cas-là, pour éviter un avertissement, la solution la plus concise est de ne pas écrire le nom du paramètre lors de la définition de la fonction : on n'écrit alors que le type du paramètre.
Avatar de koala01 koala01 - Expert éminent sénior https://www.developpez.com
le 10/04/2018 à 21:03
Citation Envoyé par Pyramidev Voir le message

Dans ce cas-là, pour éviter un avertissement, la solution la plus concise est de ne pas écrire le nom du paramètre lors de la définition de la fonction : on n'écrit alors que le type du paramètre.
Oui, jusqu'au jour où l'on va faire appel à une autre fonction -- qui utilisera cette variable -- dans le callback .
Non, ce genre d'attribut me semble particulièrement utile, vu qu'il permet de préciser au compilateur qu'il est possible (mais loin d'être certain) qu'un paramètre ne soit pas utilisé pour différentes raisons

EDIT : au fait, je n'ai jamais répondu à la question ... à combien de choix a-t-on droit pour répondre
Avatar de Bousk Bousk - Rédacteur/Modérateur https://www.developpez.com
le 10/04/2018 à 22:31
Je pense plutôt au cas où l'implémentation change selon le mode debug/release, utilisation dans un assert etc.
Contacter le responsable de la rubrique Accueil