C++ TL;DR news 1

Une petite revue d'articles hebdomadaire (peut-être)

Voici une petite revue d’articles récents, choisis et classés aléatoirement.

Lisez les autres C++ TL;DR news : https://zestedesavoir.com/billets/3947/c-tl-dr-news/

  • [Tous] Un top 7 de pièges que tous les développeurs devraient connaître
  • [C++20] Un courte introduction aux concepts
  • [Débutant] Une courte introduction aux templates

Top-7 Performance Traps for Every Developer

Lire l’article : https://www.cppstories.com/2021/perf-traps/

Beaucoup de développeuses et développeurs utilisent le C++ parce que "c’est plus performant". C’est une erreur assez classique. Le C++ permet d’optimiser, encore faut-il savoir le faire correctement. Cet article résume les 7 principales erreurs que font les développeuses et développeurs quand ils veulent optimiser un programme :

  1. faire des prédictions sur les performances
  2. faire des changements qui n’ont pas d’impact
  3. ne pas connaître ses données
  4. ne pas connaître son environnement technique
  5. suivre aveuglément la notation big-O
  6. trop optimiser son code
  7. écrire de mauvais benchmarks

Comme on le dit souvent : testez votre code, faites du profiling !

L’auteur a également écrit un livre de 175 pages sur l’optimisation du code : "Performance Analysis and Tuning on Modern CPUs", Denis Bakhvalov. Ce livre est gratuit et le lien vers le PDF est donné dans l’article.

C++20 Concepts - a Quick Introduction

Lire l’article : https://www.cppstories.com/2021/concepts-intro/

Les concepts sont une nouveauté en C++ introduite dans le C++20. Cet outil va permet de repenser complètement la façon d’écrire des templates, ce qui va avoir un impact majeur sur les codes C++. Cet article est une courte introduction aux concepts, pour bien débuter avec cet outil.

Les concepts sont un moyens de mettre des contraintes sur des paramètres template. Par exemple pouvoir exprimer qu’une paramètre template doit être un nombre entier ou doit contenir une fonction spécifique. Il est déjà possible de faire de telles choses en C++, par exemple avec le SFINAE ou enable_if, mais les concepts permettent de simplifier tout cela.

Il existe plusieurs syntaxe pour définir un concept. Par exemple pour contraindre un type d’être un entier, il est possible d’écrire le concept suivant :

template <class T>
concept integral = std::is_integral_v<T>;

Pour utiliser ce concept, il suffit alors d’utiliser cette contrainte dans un template :

template <typename T>
requires integral<T>
void DoSomething(T param) { }

Ou la version simplifiée :

void DoSomething(integral auto param) { }

Il existe également plusieurs concepts prédéfinis dans l’en-tête <concepts> : same_as, derived_from, convertible_to, etc.

L’article détaille d’autres syntaxes alternatives. Globalement, ce ne sont pas des syntaxes difficiles à retenir, il suffira de se faire un pense-bête au début, le temps de s’en souvenir. Et de copier-coller-adapter les codes de cet article !

Templates - First Steps

Lire l’article : http://www.modernescpp.com/index.php/template-get-insight

Cet article est une introduction très courte sur les templates. L’article est basé sur plusieurs questions simples qu’une personne débutante peut se poser.

1. Quand utiliser les templates ?

Pour implémenter une idée générale, qui n’est pas spécifique d’un type particulier. Par exemple "max".

2. Comment écrire un template ?

Pour transformer une fonction non template (par exemple qui utilise le type int) en template, ajoutez template <typename T> et remplacez int par T.

template <typename T>              
T max(T lhs, T rhs) {              
    return (lhs > rhs)? lhs : rhs;
}

3. Que se passe-t-il quand un template est instancié ?

Le compilateur va générer une instance de la fonction template pour chaque type utilisé.

max(10, 5);      // génère la fonction max<int>
max(10.5, 5.5);  // génère la fonction max<double>

4. Que se passe-t-il lorsqu’un template est instancié plusieurs fois avec le même type ?

Une seule instance est créée pour chaque type. L’instanciation est paresseuse : le code est généré uniquement s’il est utilisé (il est donc possible d’écrire un code template invalide, tant que celui-ci n’est pas instancié).


L’idée de cette revue de presse est de proposer du contenu hebdomadaire. Pour faciliter cela, le contenu doit être simple à rédiger et relativement courts. Et idéalement, que d’autres autrices et auteurs puissent ajouter facilement leurs revues. Pour cela, je vous propose de poster vos revues dans l’issue suivante : https://github.com/NotANameServer/discord/issues/26. Celle-ci sera publiée le dimanche 23 mai.

5 commentaires

Merci pour le billet.

J’aime assez ce format. Pour quelqu’un comme moi qui ne pratique pas le C++, mais qui s’y intéresse simplement pour la « culture technique », je trouve ça vraiment bien. C’est compréhensible et léger, ça permet de faire de la veille sans pour autant avoir une grande expertise en C++.

Mais je suppose que les gurus du C++ aussi y trouveront leur compte ;)

Salut,

Question naïve (je ne connais pas les arcanes de C++), je vois en lisant la doc de std::is_integral que la valeur renvoyée est static. J’imagine que ça signifie que la fonction peut être évaluée à la compilation. Est-ce une condition nécessaire (vu que le compilateur fait de la monomorphisation statique, j’imagine que les concepts sont vérifiés aussi à la compilation), ou bien on peut écrire un truc du genre concept foo = non_static_evaluation<T>; et la vérification est faite au runtime ?

Au delà de la lisibilité du code générique avec les concepts, on peut supposer que ça va aussi améliorer les messages d’erreur. Avoir un type T does not match concept C at line ... semble bien plus lisible/compréhensible qu’un message de 5 lignes à base de std::enable_if.

Pour répondre à @adri1, static veut dire que ça ne dépend pas de l’instance de la classe. Rapide exemple pour expliquer:

class Foo {
  // static
  static int bar;
  // pas static
  int baz;
};

Foo::bar;  // Pas besoin d'instancier la classe pour utiliser bar.
Foo foo;
foo.baz;  // Besoin d'une instance de Foo pour utiliser baz.

@adri1 Comme a dit @Berdes, static est un spécificateur lié au stockage d’une variable (https://en.cppreference.com/w/cpp/language/storage_duration), ce qui est différent de l’évaluation compile time ou runtime (il existe constexpr et consteval en C++ pour cela https://en.cppreference.com/w/cpp/language/constexpr).

Pour is_integral::value, si tu regardes la doc de integral_constant, on voit que value est static et constexpr. C’est donc bien une valeur évaluée à la compilation, mais grâce à constexpr et pas à static.

j’imagine que les concepts sont vérifiés aussi à la compilation

Vu que les concepts s’appliquent sur les types, c’est (a priori) forcément évalué au compile time en C++.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte