C++, auto et decltype

Ou comment mieux comprendre ces deux nouveautés

a marqué ce sujet comme résolu.
Auteur du sujet

Bonjour à tous,

J'ai commencé (il y a 1 semaine, 2 jours) la rédaction d'un tutoriel dont l'intitulé est C++, auto et decltype.

J'aimerais obtenir un maximum de retour sur celui-ci, sur le fond ainsi que sur la forme, afin de proposer en validation un texte de qualité.

Si vous êtes intéressé, cliquez ci-dessous

Merci d'avance pour votre aide

EDIT : n'hésitez pas à m'aider à améliorer l'article en me signalant des fautes d'orthographe, de grammaire ou de conjugaison, mais également sur le fond, si certains passages semblent peu ou pas clairs, redondants, trop complexes. Et dernière chose : j'ai besoin de l'avis de développeurs C++ : quand utilisez-vous auto et pourquoi ? Ceci afin de faire une synthèse d'arguments et de les présenter au lecteur afin que celui-ci fasse son choix.

Édité par informaticienzero

Cette réponse a aidé l’auteur du sujet

j'ai besoin de l'avis de développeurs C++ : quand utilisez-vous auto et pourquoi ? Ceci afin de faire une synthèse d'arguments et de les présenter au lecteur afin que celui-ci fasse son choix.

informaticienzero

Principalement pour les types moches et à rallonge, avec plein de templates dedans. De temps à autre je tente du AAA, mais sans trop me forcer à l'utiliser.

EDIT: sinon, de ce que j'ai lu du tuto, ça me semble clair et lisible.

Édité par Luthaf

Mon Github — Tuto Homebrew — Article Julia

+1 -0

Cette réponse a aidé l’auteur du sujet

(Je n'ai pas encore lu la dernière béta)

Pour avoir lu les chapitres concernés dans le livre de Scott Meyers, je retrouve dans ton article une grosse traduction française de ce qu'il a fait. Je trouve ça un peu dommage. D'ailleurs tu le dis toi-même, tu réutilises les exemples.

Globalement, le contenu est bien. Cependant, je trouve qu'il manque un fil rouge. Dès le début, je sais ce dont tu vas parler, mais je n'ai aucune motivation, pas de but précis. A quoi ça sert d'apprendre ces règles d'inférences ?

Il te manque une carotte je pense. Une idée (mais je ne suis pas assez connaisseur pour te donner un exemple plus précis) serait que tu soumettes un ou deux exemples accompagnés de questions et que le tutoriel y apporte les réponses nécessaires. Ce que j'ai en tête, c'est un peu ce que fait Herb sutter dans son article GOTW1 : Instanciation des variables.

Je trouve que la difficulté avec l'inférence de type en C++ c'est que la plupart des règles sont intuitives, mais il existe des pièges. Et si on ne se fait pas piéger, on va l'oublier et on tombera dedans une prochaine fois.

Bref, bonne continuation. Si j'ai le temps, je te donnerai un avis un peu plus détaillé et moins général comme je viens de le faire.

+2 -0
Auteur du sujet

Merci beaucoup pour ton retour.

Oui, j'ai beaucoup pris de son livre parce que c'est vraiment une des rares ressources que j'ai trouvé qui soit bien à jour tant sur C++11 et C++14 et surtout assez exhaustive.

Maintenant que tu le dis, c'est vrai qu'un ou deux exemples pièges en introduction pourrait mettre le lecteur en appétit. Je pense à montrer un code où l'on s'attend à avoir A comme type mais finalement c'est pas exactement ça.

Cette réponse a aidé l’auteur du sujet

J'ai survolé le tuto, mais j'ai trouvé une erreur dans le code (du moins je crois, le C++ c'est pas mon fort :p )

Dans Les règles de fonctionnement de auto sur la ligne 2 du premier code, il y a :

1
auto x = 0; // 27 est de type int, donc x aussi

Mais il n'y marqué 27 nul part.

+1 -0

Cette réponse a aidé l’auteur du sujet

Bonjour,

Je trouve que l'explication que tu donnes (bien que juste) donne une impression d'une règle avec plein d'exceptions, alors que la règle peut être exprimée de manière très générique avec moins d'exceptions.

La situation :

1
2
3
4
template<class T>
void foo(P);

foo(e);

La première étape est de déterminer le type et la catégorie de e, pour rester simple lvalue vs xvalue (j'oublie les prvalue volontairement) et le type est celui de l'objet désigné par e (donc pas de référence).

Cas général : On retire l'éventuelle référence ou const/volatile placé en premier à P, par exemple :

  • P' const devient P'
  • P'& devient P'
  • P'&& devient P'
  • P' const& devient P' const

Ensuite on fait correspondre ce P au type de e

Exceptions :

  • Si P est de la forme T&& et que e est une lvalue, on ajoute une & au type de e. Ce cas est ton paragraphe références universelles (je ne suis pas convaincu qu'il soit nécessaire d’introduire ce terme d'ailleurs).
  • Si P n'est pas de la forme P'& ou P'&&, on effectue une decay conversion ou on retire le const/volatile placé en premier (au besoin) au type de e. Ce cas est ton paragraphe passage par recopie.

Le dernier élément est que si un type U est de la forme U'& alors U&& est identique à U'&. C'est ce que tu as écris sous la forme :

Dans le cas d'une lvalue, T et ParamType sont déduits comme étant des lvalue-references. C'est le seul cas dans les règles de déduction des templates que T conserve sa référence. L'autre point surprenant est que bien que ParamType soit déclaré comme une rvalue (T && param), le compilateur en déduit que c'est une lvalue-reference.

Ce qui me gène dans la formulation que tu fais, c'est qu'il y a une impression que tout le processus de déduction change dans chaque cas, alors qu'il n'y a qu'une partie qui varie : selon la forme de P on affecte le type de e, la reste du processus est identique.

En particulier, dans ta formulation actuelle :

  1. Présenter le traitement des pointeurs comme une exception me gène, puisqu'elles ne sont pas traitées différemment d'un cas std::vector<T>;
  2. Précise que le cas référence universelle se produit uniquement dans le cas T&& et aucun autre (par exemple dans le cas T const && les règles sont les habituelles)
  3. La partie petite particularité de decltype ne traite pas le cas où e est une xvalue.
  4. Tu ne dis jamais (ou je l'ai raté) que la détermination de T est faite en cherchant le T qui rend identique le type de e et P, alors que c'est pourtant la base (les subtilités étant les transformations à effectuer sur le type de e et sur P) de la déduction des paramètres template.
+2 -0

Cette réponse a aidé l’auteur du sujet

Il y a en faite trois catégories pour les expressions en c++,

  • lvalue qui désignent un objet ou une fonction;
  • xvalue qui désignent un objet qui devrait approcher sa fin de vie;
  • prvalue le reste

Les rvalue sont les xvalue et les prvalue ensemble. En général les traiter indifféremment n'a aucun impact, sauf pour le 'decltype' si c'est une xvalue alors on ajoute '&&' au type, et pour le traitement du type de e, si x c'est une prvalue on enlève l'éventuel premier 'const/volatile'.

Pour le terme référence universelle préfère forward reference qui a été retenu pour la norme.

Si tu veux jeter un oeil à la norme (un brouillon en accès libre) sans être totalement perdu, regardes spécifiquement:

  • 3.10 §1 catégories des expressions
  • 5 §5-6 ajustement du type des expressions
  • 7.1.6.2 §4 règles de 'decltype'
  • 7.1.6.4 §7 règles de 'auto'
  • 14.8.2.1 §2-3-4 déduction des argumemts génériques
+1 -0
Ce sujet est verrouillé.