Ces dernières années, on a beaucoup parlé de la « renaissance du C++ ». Il faut admettre que Microsoft a joué un rôle majeur dans ce mouvement ; je me souviens de cette vidéo où Craig Symonds et Mohsen Agsen en parlaient.
En 2011, Microsoft a annoncé le retour du C++ dans de nombreux articles, et des experts C++ de Microsoft comme Herb Sutter ont donné de nombreuses conférences expliquant pourquoi le C++ était de retour, en recommandant surtout l'utilisation du C++ moderne. À la même époque, la norme C++11 a été approuvée, et l'on a commencé à parler du C++ comme d'un nouveau langage.
En 2011, le C++ était utilisé depuis plus de 30 ans. Il n'était pas facile de convaincre les développeurs que le nouveau C++ simplifiait réellement de nombreuses facettes frustrantes de son utilisation, et qu'il existait une nouvelle façon moderne d'améliorer le code C++.
Prenons l'exemple de la gestion de la mémoire — c'est peut-être l'un des aspects les plus critiqués du C++. Pendant de nombreuses années, l'allocation des objets se faisait avec le mot-clé new, et les développeurs devaient penser à invoquer delete quelque part dans le code. Le « C++ moderne » a résolu ce problème en promouvant l'utilisation des pointeurs partagés (shared pointers).
Lorsque C++0x a été annoncé il y a quelques années, je pensais qu'il n'aurait pas beaucoup d'impact sur le langage C++, mais je me trompais. Regardez cet extrait de code issu de Folly — on dirait qu'il a été développé avec un nouveau langage.

La même observation vaut pour la quasi-totalité du code source de Folly ; son implémentation semble très différente du code C++03.
Comment limiter l'impact du passé du C++ ?
Il n'y a pas de solution miracle. On peut espérer que les compilateurs C++ nous aident en émettant des avertissements sur les pratiques dépréciées, comme les anciennes fonctions de manipulation de chaînes (strcpy, strcat, …). Mais cette solution n'aura pas un grand impact. Le C++ moderne, c'est avant tout apprendre et pratiquer de nouveaux idiomes.
Une autre solution consisterait à considérer qu'un nouveau langage nommé «Modern C++» a été créé. Faisons la même recherche web que précédemment, mais cette fois pour l'allocation d'objets en « Modern C++ » — le premier lien parlera des smart pointers.
À la découverte du nouveau langage MC++
Une meilleure façon de découvrir la puissance de MC++ est d'explorer le code source d'un projet mature qui utilise ses fonctionnalités. Folly de Facebook est un très bon candidat.
Découvrons quelques fonctionnalités de MC++ utilisées dans Folly :
1. auto
C++11 introduit l'inférence de type via le mot-clé auto, ce qui signifie que le compilateur déduit le type d'une variable au point de déclaration. Folly utilise auto pour la quasi-totalité de ses déclarations de variables ; en voici un exemple tiré de son code source.

Utiliser le mot-clé auto vous fait gagner du temps en évitant d'écrire des choses que le compilateur connaît déjà.
2. nullptr
La constante 0 a traditionnellement joué le double rôle de constante entière et de constante de pointeur nul. C++11 corrige cela en introduisant un nouveau mot-clé servant de constante de pointeur nul distincte : nullptr.
Dans le code source de Folly, tous les pointeurs nuls sont représentés par le nouveau mot-clé nullptr ; la constante 0 n'est utilisée nulle part.
3. shared_ptr
Les smart pointers ne sont pas un concept nouveau ; de nombreuses bibliothèques les ont implémentés il y a des années, la plus populaire étant boost::shared_ptr. Ce qui est nouveau, c'est leur standardisation — il n'est plus nécessaire d'utiliser une bibliothèque externe pour travailler avec les smart pointers.
Folly utilise massivement le pointeur partagé standardisé ; il ne reste que quelques pointeurs bruts dans son code source.
4. Les énumérations fortement typées
Les énumérations « traditionnelles » du C++ exportent leurs énumérateurs dans la portée environnante, ce qui peut entraîner des collisions de noms si deux énumérations différentes dans la même portée définissent des énumérateurs portant le même nom.
C++11 introduit les mots-clés enum class. Elles n'exportent plus leurs énumérateurs dans la portée environnante. De plus, nous pouvons désormais spécifier un type sous-jacent pour une énumération.

5. static_assert
C++11 introduit une nouvelle façon de tester des assertions au moment de la compilation, grâce au nouveau mot-clé static_assert. Cette fonctionnalité est très utile pour ajouter des conditions aux paramètres de templates, comme le montre cette classe template issue du code source de Folly :

6. Les templates variadiques
Un template variadique est un template pouvant accepter un nombre arbitraire d'arguments template de n'importe quel type. Les templates de classes comme de fonctions peuvent être variadiques. Folly définit de nombreux templates variadiques ; voici deux fonctions templates variadiques issues de son code source :

7. Les boucles for basées sur des intervalles
C++11 a enrichi l'instruction for pour prendre en charge le paradigme « foreach » d'itération sur les collections. Cela rend le code plus simple et plus propre. Folly utilise abondamment cette fonctionnalité ; en voici un exemple :

8. Les listes d'initialisation
En C++03, les listes d'initialisation ne s'appliquent qu'aux tableaux ; en C++11, elles ne sont plus limitées aux tableaux. Le mécanisme permettant d'accepter une liste {}est une fonction (souvent un constructeur) acceptant un argument de type std::initializer_list<T>. Voici un exemple de fonction acceptant un std::initializer_list comme argument.

Et voici comment elle est invoquée.

9. noexcept
Si une fonction ne peut pas lever d'exception, ou si le programme n'est pas écrit pour gérer les exceptions levées par une fonction, celle-ci peut être déclarée noexcept.
En voici un exemple tiré du code source de Folly.

10. move
C++11 a introduit le concept de références rvalue (spécifiées avec &&) pour distinguer une référence à une lvalue d'une référence à une rvalue. Une lvalue est un objet qui a un nom, tandis qu'une rvalue est un objet qui n'a pas de nom (un objet temporaire). La sémantique de déplacement permet de modifier les rvalues.
Pour la prendre en charge, C++11 introduit deux nouvelles fonctions membres spéciales : le constructeur de déplacement et l' opérateur d'affectation par déplacement.


Voici un bon document qui explique mieux les avantages de la sémantique de déplacement.
11. Les lambdas
C++11 offre la possibilité de créer des fonctions anonymes, appelées fonctions lambda. Vous pouvez consulter ici pour plus de détails sur cette nouvelle fonctionnalité.
Folly les utilise dans de nombreuses fonctions ; en voici un exemple tiré de son code source :

12. Les fonctions membres spéciales explicitement définies par défaut ou supprimées
En C++03, le compilateur fournit, pour les classes qui ne les définissent pas elles-mêmes, un constructeur par défaut, un constructeur de copie, un opérateur d'affectation par copie (operator=) et un destructeur. Le programmeur peut remplacer ces versions par défaut en définissant des versions personnalisées.
Cependant, on a très peu de contrôle sur la création de ces versions par défaut. Rendre une classe intrinsèquement non copiable, par exemple, exige de déclarer un constructeur de copie et un opérateur d'affectation par copie privés sans les définir.
En C++11, certaines fonctions membres spéciales peuvent être explicitement désactivées. Par exemple, le type suivant est non copiable, ce qui rend le code plus simple et plus propre.

13. L'identifiant override
En C++03, il est possible de créer accidentellement une nouvelle fonction virtuelle alors que l'on voulait redéfinir une fonction de la classe de base.
L'identifiant spécial override signifie que le compilateur vérifiera la ou les classes de base pour voir s'il existe une fonction virtuelle avec exactement cette signature. Si ce n'est pas le cas, le compilateur signalera une erreur.
Folly utilise abondamment cette nouvelle fonctionnalité :

14. std::thread
Une classe thread (std::thread) est fournie ; elle prend un objet fonction — ainsi qu'une série optionnelle d'arguments à lui passer — à exécuter dans le nouveau thread.
En C++11, travailler avec les threads est plus simple ; voici la nouvelle façon standard de définir un thread, tirée du code source de Folly :

15. Les conteneurs non ordonnés
Un conteneur non ordonné est une sorte de table de hachage. C++11 en propose quatre standard :
- unordered_map
- unordered_set
- unordered_multimap
- unordered_multiset
Folly utilise ces nouveaux conteneurs à de nombreux endroits.

Conclusion :
Un conseil pour les nouveaux développeurs C++ : considérez que le C++ a changé de nom, et utilisez « Modern C++ » plutôt que simplement C++ dans vos recherches web. Les résultats seront très différents — une recherche sur C++ seul vous mènera souvent vers des pratiques anciennes.
