2016-09-11 2 views
0

Pourquoi initializer_list<string> ls = {"A", "B", "C"}; fonctionne?règles sur la convariance pour les modèles

Le rhs est de intializer_list<const char*>, je me demande comment il est converti en lhs. De même, comment fonctionne vector<string> vs = {"A", "B", "C"}?

Répondre

0

Les rhs est de intializer_list<const char*>

Ceci est faux. Le côté droit n'a aucun type. Ce n'est pas un objet du type initializer_list. C'est braced-init-list, une construction spéciale en langage, utilisée dans plusieurs contextes.

[dcl.init.list]/3 dit ceci au sujet de votre première question:

Liste-initialisation d'un objet ou une référence de type T est défini comme suit:
[... ]
- Sinon, si T est une spécialisation de std::initializer_list<E>, un objet prvalue initializer_list est construit comme décrit ci-dessous et utilisé pour initialiser l'objet selon les règles d'initialisation d'un objet d'une classe du même type (8.5).

[dcl.init.list]/5:

Un objet de type std::initializer_list<E> est construit à partir d'une liste d'initialisation que si l'exécution a alloué un tableau temporaire de N éléments de type const E, où N est le nombre d'éléments dans le initializer list. Chaque élément de ce tableau est initialisé avec l'élément correspondant de la liste d'initialisation et l'objet std::initializer_list<E> est construit pour faire référence à ce tableau. [Remarque: Un constructeur ou une fonction de conversion sélectionnée pour la copie doit être accessible (Article 11) dans le contexte de la liste d'initialisation. -end note] Si une conversion de rétrécissement est nécessaire pour initialiser l'un des éléments, le programme est mal formé.

En bref:

  1. D'abord, il alloue de la mémoire tableau de 3 chaînes

  2. Ensuite, il tente d'initialiser chaque chaîne avec l'élément correspondant de init-liste. Tous les éléments de la liste sont convertibles en const char* et std::string a le constructeur acceptant const char*, il est donc utilisé pour construire ces chaînes.

Dans votre deuxième question une autre clause de [dcl.init.liste]/3 est utilisé:

Liste-initialisation d'un objet ou une référence de type T est défini comme suit:
[...]
- Dans le cas contraire, si T est un type de classe, les constructeurs sont considérés. Les constructeurs applicables sont énumérés et le meilleur est choisi par la résolution de surcharge (13.3, 13.3.1.7). Si une conversion de rétrécissement (voir ci-dessous) est nécessaire pour convertir l'un des arguments, le programme est mal formé.

vector<string> a un constructeur prenant initializer_list<string>. C'est un meilleur match dans ce cas et nous sommes de retour à l'étape 1: nous devons construire initializer_list<string> de braced-init-list, que nous savons déjà comment faire.