Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.
nouvelles_fonctionnalites_du_c_11 [2014/03/10 12:05] 188.141.132.194 [Les expressions constantes généralisées] |
nouvelles_fonctionnalites_du_c_11 [2014/11/04 00:52] (Version actuelle) gbdivers |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
====== Les nouvelles fonctionnalités du C++11 ====== | ====== Les nouvelles fonctionnalités du C++11 ====== | ||
+ | |||
+ | ===== GCC 4.9 ===== | ||
+ | |||
+ | [[https://isocpp.org/blog/2014/04/gcc-4.9.0|GCC 4.9.0 Released]] | ||
===== GCC 4.8 ===== | ===== GCC 4.8 ===== | ||
Ligne 17: | Ligne 21: | ||
==== Initialisation des données membres non-statique ==== | ==== Initialisation des données membres non-statique ==== | ||
- | Norme C++ : N2756. | + | Norme C++ : [[http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2756.htm|N2756]]. |
Seules les variables membres statiques et constantes pouvaient être initialisées directement dans la déclaration de la classe. Les autres variables membres devaient être initialisées dans les constructeurs. | Seules les variables membres statiques et constantes pouvaient être initialisées directement dans la déclaration de la classe. Les autres variables membres devaient être initialisées dans les constructeurs. | ||
Ligne 92: | Ligne 96: | ||
==== Alias de templates ==== | ==== Alias de templates ==== | ||
- | Norme C++ : N2258. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf|N2258]]. |
Il n'est pas possible de déclarer un ''typedef'' pour déclarer un type template. Pour contourner cela, il faut déclarer une nouvelle classe template : | Il n'est pas possible de déclarer un ''typedef'' pour déclarer un type template. Pour contourner cela, il faut déclarer une nouvelle classe template : | ||
Ligne 154: | Ligne 158: | ||
==== Constructeurs délégués ==== | ==== Constructeurs délégués ==== | ||
- | Norme C++ : N1986. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf|N1986]]. |
Avant, lorsque l'on souhaitait déclarer plusieurs constructeurs, on retrouvait le même code recopié dans plusieurs constructeurs, ce qui alourdissait inutilement le code et nuisait à la maintenance. Avec le C++11, un constructeur peut appeler un autre constructeur directement. On peut alors mettre dans un constructeur que le code qui lui est spécifique. | Avant, lorsque l'on souhaitait déclarer plusieurs constructeurs, on retrouvait le même code recopié dans plusieurs constructeurs, ce qui alourdissait inutilement le code et nuisait à la maintenance. Avec le C++11, un constructeur peut appeler un autre constructeur directement. On peut alors mettre dans un constructeur que le code qui lui est spécifique. | ||
Ligne 169: | Ligne 173: | ||
==== Littérales définies par l'utilisateur ==== | ==== Littérales définies par l'utilisateur ==== | ||
- | Norme C++ : N2765. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2765.pdf|N2765]]. |
Le C++ accepte d'ajouter un qualificateur à la suite des constantes que l'on déclare, pour préciser le type de cette constante. Par exemple 1f indique que l'on déclare un ''float'' alors que 1L indique que l'on déclare un ''long''. Il est maintenant possible de définir ses propres qualificateurs en utilisant l'opérateur littéral operator"" : | Le C++ accepte d'ajouter un qualificateur à la suite des constantes que l'on déclare, pour préciser le type de cette constante. Par exemple 1f indique que l'on déclare un ''float'' alors que 1L indique que l'on déclare un ''long''. Il est maintenant possible de définir ses propres qualificateurs en utilisant l'opérateur littéral operator"" : | ||
Ligne 200: | Ligne 204: | ||
Les littérales définies par l'utilisateur acceptent quatre types de paramètre en entrée : | Les littérales définies par l'utilisateur acceptent quatre types de paramètre en entrée : | ||
- | les entiers, en utilisant les types ''unsigned long long'' ou ''const char*'' ; | + | * les entiers, en utilisant les types ''unsigned long long'' ou ''const char*'' ; |
- | les nombres réels, en utilisant les types ''long double'' ou ''const char*'' ; | + | * les nombres réels, en utilisant les types ''long double'' ou ''const char*'' ; |
- | les chaînes de caractères, en utilisant la paire d'arguments (''const char*'', ''size_t'') ; | + | * les chaînes de caractères, en utilisant la paire d'arguments (''const char*'', ''size_t'') ; |
- | un caractère, en utilisant le type ''char''. | + | * un caractère, en utilisant le type ''char''. |
Seuls les suffixes commençant par "_" sont autorisés. Les autres sont réservés pour un usage ultérieur par la norme. | Seuls les suffixes commençant par "_" sont autorisés. Les autres sont réservés pour un usage ultérieur par la norme. | ||
==== Déclarations étendues de l'amitié ==== | ==== Déclarations étendues de l'amitié ==== | ||
- | Norme C++ : N1791. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1791.pdf|N1791]]. |
- | L'amitié peut maintenant se transmettre via les typdef et les template : | + | L'amitié peut maintenant se transmettre via les ''typedef'' et les ''template'' : |
<code cpp> | <code cpp> | ||
Ligne 237: | Ligne 242: | ||
==== Surcharges explicites de la virtualité ==== | ==== Surcharges explicites de la virtualité ==== | ||
- | Norme C++ : N2928, N3206 et N3272. | + | Norme C++ : [[http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2928.htm|N2928]], [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3206.htm|N3206]] et [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm|N3272]]. |
Lorsque l'on dérive une classe, il est relativement facile de se tromper sur la signature d'une fonction. On déclare alors une nouvelle fonction au lieu de surcharger une fonction du parent. | Lorsque l'on dérive une classe, il est relativement facile de se tromper sur la signature d'une fonction. On déclare alors une nouvelle fonction au lieu de surcharger une fonction du parent. | ||
Ligne 290: | Ligne 295: | ||
==== La constante nullptr ==== | ==== La constante nullptr ==== | ||
- | Norme C++ : N2431. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf|N2431]]. |
Le pointeur null a longtemps été défini comme étant égal à 0. Cela pouvait poser des problèmes lors de la résolution des fonctions à appeler. En effet, 0 était considéré avant tout comme un int et non comme un pointeur null. | Le pointeur null a longtemps été défini comme étant égal à 0. Cela pouvait poser des problèmes lors de la résolution des fonctions à appeler. En effet, 0 était considéré avant tout comme un int et non comme un pointeur null. | ||
Ligne 329: | Ligne 334: | ||
==== Déclaration anticipée pour les énumérations ==== | ==== Déclaration anticipée pour les énumérations ==== | ||
- | Norme C++ : N2764. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2764.pdf|N2764]]. |
Il est maintenant possible de déclarer par anticipation les énumérations à typage fort (//strongly-typed enums//), introduites dans gcc 4.4. | Il est maintenant possible de déclarer par anticipation les énumérations à typage fort (//strongly-typed enums//), introduites dans gcc 4.4. | ||
Ligne 340: | Ligne 345: | ||
==== Les expressions constantes généralisées ==== | ==== Les expressions constantes généralisées ==== | ||
- | Norme C++ : N2235. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf|N2235]]. |
Les expressions constantes permettent de spécifier avec le mot clé ''constexpr'' qu'une expression, une fonction ou un constructeur pourra être évalué lors de la compilation. | Les expressions constantes permettent de spécifier avec le mot clé ''constexpr'' qu'une expression, une fonction ou un constructeur pourra être évalué lors de la compilation. | ||
Ligne 361: | Ligne 366: | ||
</code> | </code> | ||
- | Les expressions peuvent être utilisées pour réaliser des calculs à la compilation, similaire à ce que l'on fait avec les fonctions templates (voir par exemple La meta-programmation en C++ - Calcul et optimisation mathématique) : | + | Les expressions peuvent être utilisées pour réaliser des calculs à la compilation, similaire à ce que l'on fait avec les fonctions templates (voir par exemple [[http://loulou.developpez.com/tutoriels/cpp/metaprog/#LIII|La meta-programmation en C++ - Calcul et optimisation mathématique]]) : |
<code cpp> | <code cpp> | ||
Ligne 392: | Ligne 397: | ||
==== Les unions sans restrictions ==== | ==== Les unions sans restrictions ==== | ||
- | Norme C++ : N2544. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf|N2544]]. |
Avec le C++98, il n'était pas possible d'utiliser des types possédant un constructeur, un destructeur ou un opérateur d'affectation défini par l'utilisateur. | Avec le C++98, il n'était pas possible d'utiliser des types possédant un constructeur, un destructeur ou un opérateur d'affectation défini par l'utilisateur. | ||
Ligne 418: | Ligne 423: | ||
</code> | </code> | ||
- | Il est alors nécessaire d'utiliser les unions dans des structures appelant manuellement les fonctions qui ont été supprimées. Voici un exemple de code utilisant un membre de type string dans une union. Il est alors nécessaire d'appeler explicitement le destructeur de la chaîne et de faire un placement new pour créer une nouvelle chaîne. | + | Il est alors nécessaire d'utiliser les unions dans des structures appelant manuellement les fonctions qui ont été supprimées. Voici un exemple de code utilisant un membre de type ''string'' dans une ''union''. Il est alors nécessaire d'appeler explicitement le destructeur de la chaîne et de faire un ''placement new'' pour créer une nouvelle chaîne. |
<code cpp> | <code cpp> | ||
Ligne 453: | Ligne 458: | ||
==== Range-based for ==== | ==== Range-based for ==== | ||
- | Norme C++ : N2930. | + | Norme C++ : [[http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2930.html|N2930]]. |
- | Le range-based for permet de parcourir la totalité d'un conteneur. Cette syntaxe est compatible avec tous les conteneurs standards et les conteneurs définis par l'utilisateur en fournissant soit les fonctions membres x.begin() et x.end(), soit en fournissant les fonctions libres begin(x) et end(x). Cette syntaxe est compatible en particulier avec std::string ou les listes d'initialisation. | + | Le //range-based for// permet de parcourir la totalité d'un conteneur. Cette syntaxe est compatible avec tous les conteneurs standards et les conteneurs définis par l'utilisateur en fournissant soit les fonctions membres ''x.begin()'' et ''x.end()'', soit en fournissant les fonctions libres ''begin(x)'' et ''end(x)''. Cette syntaxe est compatible en particulier avec ''std::string'' ou les listes d'initialisation. |
<code cpp> | <code cpp> | ||
Ligne 470: | Ligne 475: | ||
==== Règles sur la génération automatique pour le déplacement et la copie ==== | ==== Règles sur la génération automatique pour le déplacement et la copie ==== | ||
- | Norme C++ : N3053. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3053.html|N3053]]. |
Cette version de gcc implémente les règles proposées dans le document N3053 relatives à la génération automatique des opérations de copie et de déplacement. Ces différentes règles permettent de comprendre quand et pourquoi le compilateur ajoute les constructeurs et opérateurs de copie et de déplacement | Cette version de gcc implémente les règles proposées dans le document N3053 relatives à la génération automatique des opérations de copie et de déplacement. Ces différentes règles permettent de comprendre quand et pourquoi le compilateur ajoute les constructeurs et opérateurs de copie et de déplacement | ||
- | Les types fondamentaux du C++ (build-in types) proposent la sémantique de déplacement similaire à la copie. | + | - Les types fondamentaux du C++ (build-in types) proposent la sémantique de déplacement similaire à la copie. |
- | Une structure est correctement formée pour la copie si et seulement si ses bases et ses membres sont correctement formés pour la copie. | + | - Une structure est correctement formée pour la copie si et seulement si ses bases et ses membres sont correctement formés pour la copie. |
- | Une structure est correctement formée pour le déplacement si et seulement si ses bases et ses membres sont correctement formés pour le déplacement. | + | - Une structure est correctement formée pour le déplacement si et seulement si ses bases et ses membres sont correctement formés pour le déplacement. |
- | Les fonctions pour la copie et le déplacement peuvent être spécifiés avec =delete et =default. | + | - Les fonctions pour la copie et le déplacement peuvent être spécifiés avec ''=delete'' et ''=default''. |
- | La sémantique de déplacement est implicitement déclarée si la structure est correctement formée et si la copie n'est pas déclarée par l'utilisateur (en utilisant =default par exemple). On doit alors ajouter explicitement le constructeur par déplacement avec : default. | + | - La sémantique de déplacement est implicitement déclarée si la structure est correctement formée et si la copie n'est pas déclarée par l'utilisateur (en utilisant ''=default'' par exemple). On doit alors ajouter explicitement le constructeur par déplacement avec : ''default''.<code cpp> |
- | <code cpp> | + | |
struct no_move { | struct no_move { | ||
no_move( const no_move& ) = default; | no_move( const no_move& ) = default; | ||
Ligne 489: | Ligne 493: | ||
}; | }; | ||
</code> | </code> | ||
+ | - De manière identique, la copie est supprimée si le déplacement est déclaré par l'utilisateur.<code cpp> | ||
+ | struct no_copy { | ||
+ | no_copy( no_copy&& ) = default; | ||
+ | }; | ||
- | De manière identique, la copie est supprimée si le déplacement est déclaré par l'utilisateur. | + | struct has_copy { |
- | <code cpp> | + | has_copy( const has_copy& ) = default; |
- | + | has_copy( has_copy&& ) = default; | |
- | struct no_copy { | + | }; |
- | no_copy( no_copy&& ) = default; | + | |
- | }; | + | |
- | + | ||
- | struct has_copy { | + | |
- | has_copy( const has_copy& ) = default; | + | |
- | has_copy( has_copy&& ) = default; | + | |
- | }; | + | |
</code> | </code> | ||
- | + | - Les unions suppriment implicitement le déplacement si l'un de leur membre possède un déplacement non-trivial. Idem pour la copie.<code cpp> | |
- | Les unions suppriment implicitement le déplacement si l'un de leur membre possède un déplacement non-trivial. Idem pour la copie. | + | |
- | + | ||
- | <code cpp> | + | |
struct non_trivial_copier { | struct non_trivial_copier { | ||
non_trivial_copier( const non_trivial_copier& ) = delete; | non_trivial_copier( const non_trivial_copier& ) = delete; | ||
Ligne 537: | Ligne 535: | ||
==== Autoriser les constructeurs par déplacement à lancer une exception ==== | ==== Autoriser les constructeurs par déplacement à lancer une exception ==== | ||
- | Norme C++ : N3050. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3050.html|N3050]]. |
- | Dans le document N2855, Doug Gregor et Dave Abrahams ont présenté la problématique qui pouvait se poser dans certains cas avec les template, les constructeurs par déplacement et les fonctions de la STL. Le choix a été fait alors d'interdire purement et simplement les constructeurs par déplacement à lancer des exceptions. Ce choix pose d'autres problèmes, en particulier pour assurer les garanties des classes et la compatibilité. D'autant plus que les problématiques potentielles ne concernent que quelques cas particuliers. La nouvelle fonction std::move_if_noexcept(x) introduite dans cette version de gcc permet de corriger ce problème et d'autoriser l'utilisation des exceptions dans les constructeurs par déplacement. Au lieu d'utiliser std::move(x), qui autorise à utiliser n'importe quel constructeur par déplacement, std::move_if_noexcept(x) autorise à utiliser uniquement les constructeurs par déplacement qui ne génèrent pas d'exception. Dans le cas contraire, le compilateur utilisera le constructeur par copie. | + | Dans le [[http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2855.html|document N2855]], Doug Gregor et Dave Abrahams ont présenté la problématique qui pouvait se poser dans certains cas avec les template, les constructeurs par déplacement et les fonctions de la STL. Le choix a été fait alors d'interdire purement et simplement les constructeurs par déplacement à lancer des exceptions. Ce choix pose d'autres problèmes, en particulier pour assurer les garanties des classes et la compatibilité. D'autant plus que les problématiques potentielles ne concernent que quelques cas particuliers. La nouvelle fonction ''std::move_if_noexcept(x)'' introduite dans cette version de gcc permet de corriger ce problème et d'autoriser l'utilisation des exceptions dans les constructeurs par déplacement. Au lieu d'utiliser ''std::move(x)'', qui autorise à utiliser n'importe quel constructeur par déplacement, ''std::move_if_noexcept(x)'' autorise à utiliser uniquement les constructeurs par déplacement qui ne génèrent pas d'exception. Dans le cas contraire, le compilateur utilisera le constructeur par copie. |
<code cpp> | <code cpp> | ||
Ligne 565: | Ligne 563: | ||
</code> | </code> | ||
- | En complément, cette version de gcc introduit le mot clé noexcept qui permet de spécifier qu'une fonction ne lance pas d'exception et ne récupère pas les exceptions qui seraient lancées par les fonctions appelées. Deux syntaxes sont possibles : noexcept et noexcept (expression). | + | En complément, cette version de gcc introduit le mot clé ''noexcept'' qui permet de spécifier qu'une fonction ne lance pas d'exception et ne récupère pas les exceptions qui seraient lancées par les fonctions appelées. Deux syntaxes sont possibles : ''noexcept'' et ''noexcept (expression)''. |
<code cpp> | <code cpp> | ||
Ligne 580: | Ligne 578: | ||
==== Les fonctions lambdas ==== | ==== Les fonctions lambdas ==== | ||
- | Norme C++ : N2927. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3050.html|N2927]]. |
Les fonctions lambda sont l'ajout le plus important de gcc 4.5. En C++98, il faut en général créer un foncteur (un objet-fonction) ou une fonction libre pour utiliser les algorithmes de la bibliothèque standard : | Les fonctions lambda sont l'ajout le plus important de gcc 4.5. En C++98, il faut en général créer un foncteur (un objet-fonction) ou une fonction libre pour utiliser les algorithmes de la bibliothèque standard : | ||
Ligne 605: | Ligne 603: | ||
</code> | </code> | ||
- | Les lambdas (ou fonctions lambda ou expressions lambda) permettent de créer facilement des foncteurs directement dans l'appel de l'algorithme : | + | Les lambdas (ou fonctions lambda ou expressions lambda) permettent de créer facilement des foncteurs directement dans l'appel de l'algorithme : |
<code cpp> | <code cpp> | ||
Ligne 621: | Ligne 619: | ||
avec : | avec : | ||
- | liste de capture : liste de variables déclarées hors de la lambda et qui seront accessibles dans la lambda ; | + | - liste de capture : liste de variables déclarées hors de la lambda et qui seront accessibles dans la lambda ; |
- | paramètres (optionnel) : paramètres qui seront envoyés par l'algorithme ; | + | - paramètres (optionnel) : paramètres qui seront envoyés par l'algorithme ; |
- | retour (optionnel) : type retourné par la lambda ; | + | - retour (optionnel) : type retourné par la lambda ; |
- | code : corps de la fonction lambda. | + | - code : corps de la fonction lambda. |
- | Les paramètres passés à la lambda | + | **Les paramètres passés à la lambda** \\ |
L'algorithme std::sort a besoin d'un prédicat qui prend deux paramètres en entrée et renvoi un booléan. | L'algorithme std::sort a besoin d'un prédicat qui prend deux paramètres en entrée et renvoi un booléan. | ||
- | Les paramètres capturés dans la lambda | + | **Les paramètres capturés dans la lambda** \\ |
Il est possible d'accéder à des variables déclarées en dehors de la lambda : | Il est possible d'accéder à des variables déclarées en dehors de la lambda : | ||
Ligne 637: | Ligne 635: | ||
</code> | </code> | ||
- | [] : capture aucune variable ; | + | - ''[]'' : capture aucune variable ; |
- | [&] : capture toutes les variables par référence ; | + | - ''[&]'' : capture toutes les variables par référence ; |
- | [=] : capture toutes les variables par copie ; | + | - ''[=]'' : capture toutes les variables par copie ; |
- | [&count] : capture la variable count par référence ; | + | - ''[&count]'' : capture la variable ''count'' par référence ; |
- | [=count] : capture la variable count par copie. | + | - ''[=count]'' : capture la variable ''count'' par copie. |
- | Les types de retour | + | **Les types de retour** \\ |
- | Habituellement, le type de retour est automatiquement déterminé à partir de l'expression return. Si aucune valeur n'est retournée, le type de retour est void. Mais il est également possible de préciser explicitement le type de retour avec la syntaxe de type de retour en suffixe. | + | Habituellement, le type de retour est automatiquement déterminé à partir de l'expression ''return''. Si aucune valeur n'est retournée, le type de retour est ''void''. Mais il est également possible de préciser explicitement le type de retour avec la syntaxe de type de retour en suffixe. |
<code cpp> | <code cpp> | ||
Ligne 655: | Ligne 653: | ||
==== Les opérateurs de conversion explicites ==== | ==== Les opérateurs de conversion explicites ==== | ||
- | Norme C++ : N2437. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf|N2437]]. |
En C++, les constructeurs prenant un seul paramètre en entrée sont appelés constructeurs de conversion (excepté celui prenant le même type et qui est appelé constructeur par copie). Ces constructeurs peuvent être appelés si nécessaire par le compilateur pour convertir les types. | En C++, les constructeurs prenant un seul paramètre en entrée sont appelés constructeurs de conversion (excepté celui prenant le même type et qui est appelé constructeur par copie). Ces constructeurs peuvent être appelés si nécessaire par le compilateur pour convertir les types. | ||
Ligne 715: | Ligne 713: | ||
==== Les chaînes littérales brutes et unicode ==== | ==== Les chaînes littérales brutes et unicode ==== | ||
- | Norme C++ : N2442. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm|N2442]]. |
En C++, les caractères spéciaux sont codés dans les chaînes de caractères à l'aide du caractère d'échappement '\'. Par exemple, '\n' représente un retour à la ligne et '\t' représente une tabulation. Pour entrer le caractère '\', il faut donc le doubler pour ne pas le confondre avec le caractère d'échappement '\\'. Dans certains cas, par exemple dans les expressions régulières, on utilise souvent le caractère '\'. Il devient alors fastidieux de doubler ce caractère à chaque fois. Par exemple, pour écrire l'expression régulière correspondant à deux caractères séparés par '\' s'écrit "\w\\\w". Elle sera codé en C++ par : | En C++, les caractères spéciaux sont codés dans les chaînes de caractères à l'aide du caractère d'échappement '\'. Par exemple, '\n' représente un retour à la ligne et '\t' représente une tabulation. Pour entrer le caractère '\', il faut donc le doubler pour ne pas le confondre avec le caractère d'échappement '\\'. Dans certains cas, par exemple dans les expressions régulières, on utilise souvent le caractère '\'. Il devient alors fastidieux de doubler ce caractère à chaque fois. Par exemple, pour écrire l'expression régulière correspondant à deux caractères séparés par '\' s'écrit "\w\\\w". Elle sera codé en C++ par : | ||
Ligne 741: | Ligne 739: | ||
</code> | </code> | ||
- | Les chaînes brutes peuvent être précédées par un préfixe spécifiant l'encodage (u8, u, U ou L). | + | Les chaînes brutes peuvent être précédées par un préfixe spécifiant l'encodage (''u8'', ''u'', ''U'' ou ''L''). |
<code cpp> | <code cpp> | ||
Ligne 749: | Ligne 747: | ||
==== Les caractères universels dans les littérales ==== | ==== Les caractères universels dans les littérales ==== | ||
- | Norme C++ : N2170. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2170.html|N2170]]. |
La norme du C++ spécifie les types de caractères qui sont acceptés ou non dans les chaînes. En particulier, les caractères de contrôles (00 à 1F et 7F à 9F) sont interdits. Il est alors nécessaire d'utiliser les caractères d'échappement pour les utiliser dans une chaîne, ce qui peut rendre le code dépendant de la plateforme. Par exemple, la chaîne "\u0085" en windows-1252 sera écrite "\xC2\x85" en UTF-8. Pour améliorer les supports de l'unicode, le C++11 lève cette limitation. | La norme du C++ spécifie les types de caractères qui sont acceptés ou non dans les chaînes. En particulier, les caractères de contrôles (00 à 1F et 7F à 9F) sont interdits. Il est alors nécessaire d'utiliser les caractères d'échappement pour les utiliser dans une chaîne, ce qui peut rendre le code dépendant de la plateforme. Par exemple, la chaîne "\u0085" en windows-1252 sera écrite "\xC2\x85" en UTF-8. Pour améliorer les supports de l'unicode, le C++11 lève cette limitation. | ||
Ligne 755: | Ligne 753: | ||
==== Les types POD revisités ==== | ==== Les types POD revisités ==== | ||
- | Norme C++ : N2342. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm|N2342]]. |
- | Les types POD (Plain Old Data) sont des structures en C++ similaires aux structures en C, qui peuvent être en particulier copiées avec memcpy() et initialisées avec memset(). | + | Les types POD (//Plain Old Data//) sont des structures en C++ similaires aux structures en C, qui peuvent être en particulier copiées avec ''memcpy()'' et initialisées avec ''memset()''. |
<code cpp> | <code cpp> | ||
Ligne 765: | Ligne 763: | ||
</code> | </code> | ||
- | Le C++11 étend les types POD aux structures simples qui peuvent être copiées avec memcpy(). Le type S2 devient donc un type POD dans la nouvelle norme. Pour qu'un type soit un POD, il faut donc que : | + | Le C++11 étend les types POD aux structures simples qui peuvent être copiées avec ''memcpy()''. Le type ''S2'' devient donc un type POD dans la nouvelle norme. Pour qu'un type soit un POD, il faut donc que : |
- | tous ses membres soient des types POD ; | + | * tous ses membres soient des types POD ; |
- | aucune fonction virtuelle ; | + | * aucune fonction virtuelle ; |
- | pas de base virtuelle ; | + | * pas de base virtuelle ; |
- | pas de référence ; | + | * pas de référence ; |
- | pas d'accès multiple. | + | * pas d'accès multiple. |
==== Les types locaux et non nommés comme arguments template ==== | ==== Les types locaux et non nommés comme arguments template ==== | ||
- | Norme C++ : N2657. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm|N2657]]. |
En C++98, les types locaux et non-nommés ne pouvaient pas être utilisés comme arguments template. Il fallait alors déclarer les foncteurs à distance du code les utilisant, ce qui diminuait la lisibilité des algorithmes de la STL. Le C++11 permet de lever cette interdiction. | En C++98, les types locaux et non-nommés ne pouvaient pas être utilisés comme arguments template. Il fallait alors déclarer les foncteurs à distance du code les utilisant, ce qui diminuait la lisibilité des algorithmes de la STL. Le C++11 permet de lever cette interdiction. | ||
Ligne 811: | Ligne 809: | ||
==== Paramètres template étendus pour les templates template variadic ==== | ==== Paramètres template étendus pour les templates template variadic ==== | ||
- | Norme C++ : N2555. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm|N2555]]. |
Lors de l'ajout des variadics templates dans gcc 4.3, il n'était pas possible de les utiliser pour les template template. Pour les bibliothèques utilisant des variadic template template, il était donc nécessaire de dupliquer le code, comme cela se faisait lorsque les variadic template n'étaient pas disponibles. Par exemple, ce code utilisant Boost.MPL (metaprogramming language) : | Lors de l'ajout des variadics templates dans gcc 4.3, il n'était pas possible de les utiliser pour les template template. Pour les bibliothèques utilisant des variadic template template, il était donc nécessaire de dupliquer le code, comme cela se faisait lorsque les variadic template n'étaient pas disponibles. Par exemple, ce code utilisant Boost.MPL (metaprogramming language) : | ||
Ligne 845: | Ligne 843: | ||
</code> | </code> | ||
- | Malheureusement, la norme indique que T ne pourra correspondre qu'avec les templates possédant la même signature, donc uniquement des variadic template. Ici, std::tuple‹int, float> (dont la définition est std::tuple‹typename...>) pourra correspondre mais std::pair‹int, float> (dont la définition est std::pair‹T, U>) ne le pourra pas. Il est donc nécessaire de continuer à déclarer d'autres formes de template pour correspondre aux autres signatures possibles : | + | Malheureusement, la norme indique que T ne pourra correspondre qu'avec les templates possédant la même signature, donc uniquement des variadic template. Ici, ''std::tuple‹int, float>'' (dont la définition est ''std::tuple‹typename...>'') pourra correspondre mais ''std::pair‹int, float>'' (dont la définition est ''std::pair‹T, U>'') ne le pourra pas. Il est donc nécessaire de continuer à déclarer d'autres formes de template pour correspondre aux autres signatures possibles : |
<code cpp> | <code cpp> | ||
Ligne 859: | Ligne 857: | ||
Cette limitation est inutile et peut troubler les utilisateurs. Il est alors nécessaire de faciliter la correspondance des variadic template template avec les syntaxes que l'on pourra attendre. La règle est donc la suivante : | Cette limitation est inutile et peut troubler les utilisateurs. Il est alors nécessaire de faciliter la correspondance des variadic template template avec les syntaxes que l'on pourra attendre. La règle est donc la suivante : | ||
- | Étant donné un paramètre template template P dont la liste de paramètres template se termine par un "template parameter pack", P peut correspondre avec n'importe quel argument template A avec une liste de paramètres template qui est identique à la liste des paramètres template de P jusqu'au "pack", suivi par une liste de paramètres template qui correspond avec le pack en type et en genre "kind" (mais qui n'est pas nécessairement un pack lui même). | + | //Étant donné un paramètre template template P dont la liste de paramètres template se termine par un "template parameter pack", P peut correspondre avec n'importe quel argument template A avec une liste de paramètres template qui est identique à la liste des paramètres template de P jusqu'au "pack", suivi par une liste de paramètres template qui correspond avec le pack en type et en genre "kind" (mais qui n'est pas nécessairement un pack lui même).// |
Le code suivant : | Le code suivant : | ||
Ligne 899: | Ligne 898: | ||
==== Initializer-list ==== | ==== Initializer-list ==== | ||
- | Norme C++ : N2672. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2672.htm|N2672]]. |
- | Pour initialiser un tableau statique en C++98, on peut fournir une liste d'éléments pour l'initialisation (array-initializer). Si la taille n'est pas spécifiée, celle-ci est déterminée en fonction du nombre d'éléments de la liste. Si la taille est spécifiée, il faut que cette taille soit supérieure ou égale au nombre d'éléments de la liste. Le reste du tableau est complété avec les valeurs par défaut si nécessaire. | + | Pour initialiser un tableau statique en C++98, on peut fournir une liste d'éléments pour l'initialisation (//array-initializer//). Si la taille n'est pas spécifiée, celle-ci est déterminée en fonction du nombre d'éléments de la liste. Si la taille est spécifiée, il faut que cette taille soit supérieure ou égale au nombre d'éléments de la liste. Le reste du tableau est complété avec les valeurs par défaut si nécessaire. |
<code cpp> | <code cpp> | ||
Ligne 910: | Ligne 909: | ||
</code> | </code> | ||
- | Si on souhaitait créer un tableau dynamique en utilisant un vector, il était nécessaire de passer par le tableau statique avant : | + | Si on souhaitait créer un tableau dynamique en utilisant un ''vector'', il était nécessaire de passer par le tableau statique avant : |
<code cpp> | <code cpp> | ||
Ligne 918: | Ligne 917: | ||
</code> | </code> | ||
- | Pour uniformiser la syntaxe, le C++11 introduit la possibilité d'utiliser les std::initializer_list‹T>. On peut alors créer une fonction utilisant directement ce type de paramètre : | + | Pour uniformiser la syntaxe, le C++11 introduit la possibilité d'utiliser les ''std::initializer_list‹T>''. On peut alors créer une fonction utilisant directement ce type de paramètre : |
<code cpp> | <code cpp> | ||
Ligne 948: | Ligne 947: | ||
</code> | </code> | ||
- | Les conteneurs (vector, list, etc.), les chaînes de caractères (string) et les expressions régulières (regex) de la bibliothèque standard ont été mis à jour pour pouvoir utiliser directement cette syntaxe. Pour les structures plus complexes, il est possible d'emboîter plusieurs initializer-list : | + | Les conteneurs (''vector'', ''list'', etc.), les chaînes de caractères (''string'') et les expressions régulières (''regex'') de la bibliothèque standard ont été mis à jour pour pouvoir utiliser directement cette syntaxe. Pour les structures plus complexes, il est possible d'emboîter plusieurs initializer-list : |
<code cpp> | <code cpp> | ||
Ligne 999: | Ligne 998: | ||
==== Les énumérations à typage fort ==== | ==== Les énumérations à typage fort ==== | ||
- | Norme C++ : N2347. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf|N2347]]. |
- | Les énumérations permettent une liste d'identifiants en leur attribuant automatiquement des valeurs par défaut, en commençant à 0. Par exemple, le code suivant permet de créer les identifiants Nord, Est, Sud et Ouest en leur attribuant respectivement les valeurs 0 à 3. | + | Les énumérations permettent une liste d'identifiants en leur attribuant automatiquement des valeurs par défaut, en commençant à 0. Par exemple, le code suivant permet de créer les identifiants ''Nord'', ''Est'', ''Sud'' et ''Ouest'' en leur attribuant respectivement les valeurs 0 à 3. |
<code cpp> | <code cpp> | ||
Ligne 1029: | Ligne 1028: | ||
</code> | </code> | ||
- | Le C++11 propose les énumérations fortement typées, qui ne sont pas implicitement converties en entiers. Elles s'utilisent en ajoutant le mot clé class devant le nom de l'énumération : | + | Le C++11 propose les énumérations fortement typées, qui ne sont pas implicitement converties en entiers. Elles s'utilisent en ajoutant le mot clé ''class'' devant le nom de l'énumération : |
<code cpp> | <code cpp> | ||
Ligne 1041: | Ligne 1040: | ||
</code> | </code> | ||
- | Pour utiliser cette énumération, il est alors nécessaire de préciser le nom de l'énumération devant la valeur. Il n'est pas possible de convertir automatiquement en entier, mais il est possible de le faire en utilisant une conversion explicite avec static_cast : | + | Pour utiliser cette énumération, il est alors nécessaire de préciser le nom de l'énumération devant la valeur. Il n'est pas possible de convertir automatiquement en entier, mais il est possible de le faire en utilisant une conversion explicite avec ''static_cast'' : |
<code cpp> | <code cpp> | ||
Ligne 1092: | Ligne 1091: | ||
</code> | </code> | ||
- | Il est possible de récupérer le type sous-jacent d'une énumération, par exemple dans une classe template dont l'énumération est passée en argument en utilisant la fonction std::underlying_type fournie par la bibliothèque standard type traits : | + | Il est possible de récupérer le type sous-jacent d'une énumération, par exemple dans une classe template dont l'énumération est passée en argument en utilisant la fonction ''std::underlying_type'' fournie par la bibliothèque standard ''type traits'' : |
<code cpp> | <code cpp> | ||
Ligne 1122: | Ligne 1121: | ||
==== Les nouveaux types de caractères ==== | ==== Les nouveaux types de caractères ==== | ||
- | Norme C++ : N2249. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2249.html|N2249]]. |
- | Pour ajouter la prise en charge des chaînes de caractères Unicode, le nouveau standard ajoute plusieurs nouvelles fonctionnalités. Pour commencer, les nouveaux types char16_t et char32_t sont ajoutés, ainsi que le nouveau fichier d'en-tête ‹cuchar>. De plus, les nouvelles chaînes et caractères littéraux suivantes sont ajoutés : | + | Pour ajouter la prise en charge des chaînes de caractères Unicode, le nouveau standard ajoute plusieurs nouvelles fonctionnalités. Pour commencer, les nouveaux types ''char16_t'' et ''char32_t'' sont ajoutés, ainsi que le nouveau fichier d'en-tête ''‹cuchar>''. De plus, les nouvelles chaînes et caractères littéraux suivantes sont ajoutés : |
<code cpp> | <code cpp> | ||
Ligne 1152: | Ligne 1151: | ||
</code> | </code> | ||
- | Le type string, fourni par la STL est compatible avec les différents types de représentation des caractères (char, wchar_t, char16_t, char32_t). Pour tester la disponibilité de ces types, il est possible d'utiliser les macros __STDC_UTF_16__ et __STDC_UTF_32__ définis dans ‹cuchar>. | + | Le type ''string'', fourni par la STL est compatible avec les différents types de représentation des caractères (''char'', ''wchar_t'', ''char16_t'', ''char32_t''). Pour tester la disponibilité de ces types, il est possible d'utiliser les macros ''__STDC_UTF_16__'' et ''__STDC_UTF_32__'' définis dans ''‹cuchar>''. |
- | L'en-tête ‹cuchar> fournit également les fonctions de conversion de char en char16_t et char32_t et réciproquement : mbrtoc16, c16rtomb, mbrtoc32 et c32rtomb. | + | L'en-tête ''‹cuchar>'' fournit également les fonctions de conversion de ''char'' en ''char16_t'' et ''char32_t'' et réciproquement : ''mbrtoc16'', ''c16rtomb'', ''mbrtoc32'' et ''c32rtomb''. |
<code cpp> | <code cpp> | ||
Ligne 1166: | Ligne 1165: | ||
==== Les fonctions par défaut et supprimées ==== | ==== Les fonctions par défaut et supprimées ==== | ||
- | Norme C++ : N2346. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm|N2346]]. |
Dans la sémantique d'entité, il est nécessaire désactiver la copie. Par défaut, le compilateur crée automatiquement le constructeur par copie et l'opérateur d'affectation pour autoriser la copie. Pour éviter cela, il était habituel de rencontrer la syntaxe suivante, dans laquelle ces fonctions sont déclarées comme membres privés : | Dans la sémantique d'entité, il est nécessaire désactiver la copie. Par défaut, le compilateur crée automatiquement le constructeur par copie et l'opérateur d'affectation pour autoriser la copie. Pour éviter cela, il était habituel de rencontrer la syntaxe suivante, dans laquelle ces fonctions sont déclarées comme membres privés : | ||
Ligne 1178: | Ligne 1177: | ||
</code> | </code> | ||
- | Pour simplifier l'écriture, le C++11 introduit le mot clé delete pour annuler la déclaration automatique de ces fonctions. | + | Pour simplifier l'écriture, le C++11 introduit le mot clé ''delete'' pour annuler la déclaration automatique de ces fonctions. |
<code cpp> | <code cpp> | ||
Ligne 1198: | Ligne 1197: | ||
</code> | </code> | ||
- | Pour éviter d'avoir à ré-écrire du code trivial, le C++11 introduit le nouveau mot clé default permettant d'indiquer au compilateur qu'il doit générer les fonctions par défaut : | + | Pour éviter d'avoir à ré-écrire du code trivial, le C++11 introduit le nouveau mot clé ''default'' permettant d'indiquer au compilateur qu'il doit générer les fonctions par défaut : |
<code cpp> | <code cpp> | ||
Ligne 1209: | Ligne 1208: | ||
</code> | </code> | ||
- | Le mot clé default peut être utilisé avec n'importe quelle fonction qui peut être générée automatiquement par le compilateur (son utilisation peut même être redondante). Le mot clé delete peut être utilisé avec n'importe quelle fonction. Il est ainsi possible d'éviter les conversions implicites des paramètres entrants : | + | Le mot clé ''default'' peut être utilisé avec n'importe quelle fonction qui peut être générée automatiquement par le compilateur (son utilisation peut même être redondante). Le mot clé ''delete'' peut être utilisé avec n'importe quelle fonction. Il est ainsi possible d'éviter les conversions implicites des paramètres entrants : |
<code cpp> | <code cpp> | ||
Ligne 1232: | Ligne 1231: | ||
==== Sizeof étendu ==== | ==== Sizeof étendu ==== | ||
- | Norme C++ : N2253. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2253.html|N2253]]. |
- | Dans le C++98, il n'est pas possible de faire référence dans sizeof à une donnée membre non statique sans instancier cette classe. Le C++11 supprime cette limitation. | + | Dans le C++98, il n'est pas possible de faire référence dans ''sizeof'' à une donnée membre non statique sans instancier cette classe. Le C++11 supprime cette limitation. |
<code cpp> | <code cpp> | ||
Ligne 1254: | Ligne 1253: | ||
</code> | </code> | ||
- | ==== Les espace de noms inline (association d'espaces de noms) ==== | + | ==== Les espaces de noms inline (association d'espaces de noms) ==== |
- | Norme C++ : N2535. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2535.htm|N2535]]. |
Les espaces de noms inline sont un mécanisme permettant de faciliter l'évolution des bibliothèques en proposant une forme de versionning. | Les espaces de noms inline sont un mécanisme permettant de faciliter l'évolution des bibliothèques en proposant une forme de versionning. | ||
Ligne 1290: | Ligne 1289: | ||
==== La propagation des exceptions ==== | ==== La propagation des exceptions ==== | ||
- | Norme C++ : N2179. | + | Norme C++ : [[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2179.html|N2179]]. |
- | Pour faciliter la manipulation des exceptions en dehors des blocs catch, par exemple pour propager les exceptions entre les threads, la norme C++11 introduit un nouveau type et trois nouvelles fonctions : | + | Pour faciliter la manipulation des exceptions en dehors des blocs ''catch'', par exemple pour propager les exceptions entre les threads, la norme C++11 introduit un nouveau type et trois nouvelles fonctions : |
<code cpp> | <code cpp> | ||
Ligne 1305: | Ligne 1304: | ||
</code> | </code> | ||
- | Le type exception_ptr fait référence à une exception, une copie d'une exception ou vers nullptr s'il n'y a pas d'exception en cours (attention, exception_ptr n'est pas un pointeur et ne peut pas être déréférencé). On peut récupérer l'exception courante en utilisant la fonction current_exception dans un bloc catch. Les deux autres fonctions, comme leurs noms l'indiquent, permettent de relancer une exception (dans un bloc throw donc, pour pouvoir la recapturer) et de copier une exception. | + | Le type ''exception_ptr'' fait référence à une exception, une copie d'une exception ou vers ''nullptr'' s'il n'y a pas d'exception en cours (attention, ''exception_ptr'' n'est pas un pointeur et ne peut pas être déréférencé). On peut récupérer l'exception courante en utilisant la fonction ''current_exception'' dans un bloc ''catch''. Les deux autres fonctions, comme leurs noms l'indiquent, permettent de relancer une exception (dans un bloc ''throw'' donc, pour pouvoir la recapturer) et de copier une exception. |
<code cpp> | <code cpp> | ||
Ligne 1375: | Ligne 1374: | ||
===== Conclusion ===== | ===== Conclusion ===== | ||
- | documentation de gcc 4.7 ; | + | * documentation de [[http://gcc.gnu.org/projects/cxx0x.html|gcc 4.7]] ; |
- | FAQ C++11 sur le site de Bjarne Stroustrup ; | + | * [[http://www.stroustrup.com/C++11FAQ.html|FAQ C++11]] sur le site de Bjarne Stroustrup ; |
- | Overview of the new C++0x de Scott Meyers (2010). | + | * Overview of the new C++11 de Scott Meyers (2010). |
- | Remarque : le code est directement issu de la documentation de gcc, utilisable selon les termes de la licence consultable à la fin de cette page, ainsi que des drafts du comité de normalisation dont les liens sont donnés. | + | * [[http://www.codergears.com/Blog/?p=431|Learn from Folly source code the new C++11 features]] : exemple d'utilisation intensive du C++11 dans Folly (la bibliothèque C++ créée par Facebook) |
+ | |||
+ | Remarque : le code est directement issu de la documentation de gcc, utilisable selon les termes de la licence consultable à la fin de [[http://gcc.gnu.org/gcc-4.7/changes.html|cette page]], ainsi que des drafts du comité de normalisation dont les liens sont donnés. | ||
{{tag> C++ C++11 GCC}} | {{tag> C++ C++11 GCC}} |