Appel du constructeur avec des accolades à la place des parenthèses

J’ai récemment réalisé qu’en C ++ 11, nous pouvions appeler un constructeur de liste d’initialisation délégué, comme

Foo() : Foo{42} // delegate to Foo(initializer_list) 

Cette syntaxe est-elle correcte? Cela semble être le cas, bien que je me serais attendu à toujours utiliser des parenthèses pour appeler une fonction, comme Foo({42}) . L’exemple de code ci-dessous comstack bien dans clang ++ et g ++

 #include  #include  struct Foo { Foo() : Foo{42} // I would have expected invalid syntax, use Foo({42}) { std::cout << "Foo()... delegating constructor\n"; } Foo(std::initializer_list) { std::cout << "Foo(initializer_list)\n"; } }; int main() { Foo foo; } 

Je connais bien l’initialisation uniforme, comme la déclaration d’ objects avec { } , mais je ne savais pas que nous pouvions aussi appeler des constructeurs. Nous ne pouvons pas appeler de fonctions, les éléments suivants ne comstacknt pas :

 #include  void f(std::initializer_list){} int main() { f{5}; // comstack time error, must use f({5}) } 

Donc, pour résumer, ma question est la suivante: existe-t-il des règles spéciales lors de la délégation de constructeurs, qui permettent d’appeler un constructeur init-list en utilisant uniquement des accolades, comme Foo{something} ?

Oui, un initialiseur de mémoire tel que Foo{42} peut contenir une liste d’expressions entre parenthèses ou une liste d’ initiation barrée . Ceci est le cas indépendamment du fait que mem-initializer-id désigne la classe du constructeur, une classe de base ou un membre: c’est-à-dire, lorsque le constructeur délègue ou non. Voir la grammaire dans [class.base.init].

De plus, la norme spécifie ([class.base.init] / 7 en C ++ 14) que l’initialisation par la liste d’expressions ou la liste dressée-initiée se produit conformément aux règles d’initialisation habituelles. Par conséquent, si l’initialiseur est une liste std::initializer_list constructeurs std::initializer_list seront privilégiés pour la résolution de surcharge.

Je pense que la règle est assez claire: vous serez autorisé à déléguer à un constructeur de liste d’initialiseurs (c’est moi qui souligne):

Si le nom de la classe elle-même apparaît en tant que classe ou identificateur dans la liste d’initialisation de membre, la liste doit alors être composée de cet initialiseur de membre uniquement; ce constructeur s’appelle constructeur délégué, et le constructeur sélectionné par le seul membre de la liste d’initialiseurs est le constructeur cible. Dans ce cas, le constructeur cible est sélectionné par résolution de surcharge et est exécuté en premier, puis la commande retourne au constructeur délégué et son corps est exécuté.

Donc, par résolution de surcharge, vous pouvez appeler le constructeur de votre liste d’initialisation comme si vous l’appeliez dans un code «normal» parce que.

Cependant, je ne sais rien qui permette d’appeler une fonction qui accepte une liste d’initialiseurs de la même manière que vous pouvez appeler un constructeur avec un seul.

Edit: En savoir plus sur les règles du constructeur (Emphasis again mine):

Le corps d’une définition de fonction de tout constructeur, avant l’accolade ouvrante de l’instruction composée, peut inclure la liste d’initialiseurs de membres, dont la syntaxe est le signe deux-points:, suivie de la liste séparée par des virgules d’un ou de plusieurs initialiseurs de membres, chacun dont la syntaxe est la suivante
classe ou identifiant (liste d’expressions (facultatif)) (1)
classe ou identificateur brace-init-list (2) (depuis C ++ 11)
parameter-pack … (3) (depuis C ++ 11)

1) Initialise la base ou le membre nommé par class-or-identifier en utilisant une initialisation directe ou, si expression-list est vide, une initialisation de valeur
2) initialise la base ou le membre nommé par la classe ou l’identifiant à l’aide de l’initialisation de liste (qui devient l’initialisation de valeur si la liste est vide et l’initialisation d’agrégat lors de l’initialisation d’un agrégat)
3) Initialise plusieurs bases en utilisant une extension de pack

Donc, selon le n ° 2, il semble que ce soit légal.