É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 2018-04-09 12:21:04, 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 :
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:
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 :
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.
Pour une initialisation directe, C++ 17 introduit de nouvelles règles:
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.
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
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++ : |
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; } } |
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++ : |
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++ : |
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++ : |
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++ : |
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 ?
Voir aussi :
-
BkteroModérateurLa liste complète peut être trouvée ici : https://isocpp.org/files/papers/p0636r0.htmlle 09/04/2018 à 14:42
-
BkteroModérateurMince 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 :
- if constexpr : j'utilise ça dans une classe template de calcul en virgule fixe pour faire des choix en fonction des paramètres fournis.
- __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. - [[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 avecle 10/04/2018 à 14:29 -
PyramidevExpert éminentPour 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.
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.le 10/04/2018 à 19:00 -
koala01Expert éminent séniorOui, 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épondrele 10/04/2018 à 21:03 -
BouskRédacteur/ModérateurJe pense plutôt au cas où l'implémentation change selon le mode debug/release, utilisation dans un assert etc.le 10/04/2018 à 22:31
-
cambouiMembre éprouvéJ'adore, je suis fan !
J'en redemande avec C++20mê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 : 1
2
3
4
5
6
7
8
9
10
11
12
13
14struct 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"}, ... };
(mais je n'ai pas creusé pourquoi, on ne touche pas à un code qui fonctionne...) le 10/04/2018 à 10:24 -
koala01Expert éminent séniorEt en déclarant ton tableau static constexpr
PS: au passage: pourquoi long pour sortableun 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 superfluele 10/04/2018 à 11:49 -
wolinnMembre éprouvé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.le 10/04/2018 à 12:30
-
BouskRédacteur/ModérateurMon 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++17le 10/04/2018 à 15:58