8 votes

Quel est le type de {objet} ?

Considérons le morceau de code suivant :

void foo (M&) {}

M m;
foo ({m});

Ainsi, l'expression {m} est traitée comme une référence à une valeur rationnelle et c'est pourquoi ce code ne peut pas être compilé.

Est-il vrai que {object} produit toujours un objet temporaire ?

Si ce n'est pas le cas, comment s'en assurer lorsque cela se produit ? Si oui, veuillez considérer le code suivant :

struct M {};

struct I {
    I (M&) {}
};

struct MM {
    MM (M& p)
    : m (p), i ( {p} )
    {}

    M& m;
    I i;
};

M m;
MM mm {m};

Ici, il n'y a aucun problème, alors quelle est la différence entre {m} du premier exemple et {p} de la seconde ?

Résultats du compilateur (GCC 4.8.1) (premier exemple) :

main.cpp:366:13: error: invalid initialization of non-const reference of type ‘M&’ from an rvalue of type ‘<brace-enclosed initializer list>’
     foo ({m});
             ^
main.cpp:359:6: error: in passing argument 1 of ‘void foo(M&)’
 void foo (M&) {}

2voto

TartanLlama Points 1461

Quel est le type de {object} ?

Cela dépend du contexte. Dans certaines situations, par exemple lors de la construction d'un type avec un std::initializer_list il sera de type std::initializer_list<decltype(object)> . Dans d'autres cas, il sera utilisé pour initialiser les membres d'un agrégat ou d'un autre type, auquel cas la forme syntaxique {object} ne avoir un type en soi .

Est-il vrai que {object} produit toujours un objet temporaire ?

Non, et dans votre cas, cela ne devrait pas être le cas. C'était un bogue dans la spécification C++11 concernant l'ordre des clauses spécifiant l'initialisation de la liste. L'ancienne formulation signifiait que votre appel entraînait la construction d'un temporaire (ce qui est mal formé en raison du paramètre de référence non-const), mais selon les nouvelles règles, la référence est liée à l'unique élément de la liste d'initialisation. Votre ancien compilateur implémente l'ancienne formulation, alors que compilateurs plus récents mettre en œuvre le comportement fixé.

Ici, il n'y a aucun problème, alors quelle est la différence entre {m} du premier exemple et {p} du second ?

La différence est que {m} est utilisé pour initialiser le M paramètre de foo (invalide selon l'ancienne formulation), mais {p} initialise le I membre. En tant que tel, p est pris comme argument de la fonction I se lie au constructeur M& et puisque le paramètre p est une valeur l, tout va bien.

0voto

Marco A. Points 18535

Est-il vrai que {objet} produit toujours un objet temporaire ?

Non (lire la suite).

Les deux extraits sont valides (vous devriez utiliser un compilateur à jour) et seront compilés avec succès.

En {p} L'affaire relève de la catégorie [over.match.list]/p1

Lorsque des objets de classe non agrégée de type T sont initialisés par liste de telle sorte que [dcl.init.list] spécifie que la résolution de surcharge est effectuée conformément aux règles de cette section, la résolution de surcharge sélectionne le constructeur en deux phases :

(1.1) Initialement, les fonctions candidates sont les constructeurs de la liste d'initialisation ([dcl.init.list]) de la classe T et la liste d'arguments est constituée de la liste d'initialisation en tant qu'argument unique.

(1.2) Si aucun constructeur viable de la liste d'initialisation n'est trouvé, la résolution de surcharge est à nouveau effectuée, les fonctions candidates étant tous les constructeurs de la classe T et la liste d'arguments étant constituée des éléments de la liste d'initialisation.

Plus précisément, dans (1.2), alors que {m} est une initialisation de liste pour l'autre cas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X