Pourquoi std:: initializer list n'est-il pas un langage intégré?

pourquoi std::initializer_list n'est-il pas un langage de base intégré?

il me semble que C'est une caractéristique assez importante de C++11 et pourtant il n'a pas son propre mot-clé réservé (ou quelque chose du même genre).

à la place, initializer_list il est juste une classe de modèle de la bibliothèque standard qui a un spécial, implicite cartographie de la nouvelle attaché-INIT-list {...} syntaxe gérée par le compilateur.

à première vue, Cette solution est tout à fait hacky .

est-ce la façon dont les nouveaux ajouts au langage C++ seront maintenant mis en œuvre: par rôles implicites de certaines classes de modèles et non par le langage de base ?


veuillez considérer ces exemples:

   widget<int> w = {1,2,3}; //this is how we want to use a class

pourquoi une nouvelle classe choisie:

   widget( std::initializer_list<T> init )

au lieu d'utiliser quelque chose similaire à l'une de ces idées:

   widget( T[] init, int length )  // (1)
   widget( T... init )             // (2)
   widget( std::vector<T> init )   // (3)
  1. un tableau classique, vous pourriez probablement ajouter const ici et là
  2. trois points existent déjà dans la langue (var-args, maintenant modèles variadiques), pourquoi ne pas réutiliser la syntaxe (et lui faire sentir incorporé )
  3. juste un conteneur existant, pourrait ajouter const et &

tous font déjà partie de la langue. Je n'ai écrit que mes 3 premières idées, je suis sûr qu'il ya beaucoup autres approches.

91
demandé sur emesx 2013-03-04 13:58:52

6 réponses

il y avait déjà des exemples de fonctions linguistiques" de base "qui renvoyaient des types définis dans l'espace de noms std . typeid renvoie std::type_info et (étirement d'un point peut-être) sizeof renvoie std::size_t .

dans le premier cas, vous devez déjà inclure un en-tête standard afin d'utiliser cette fonctionnalité appelée" core language".

maintenant, pour les listes d'initialiseur il se trouve qu'aucun mot-clé n'est nécessaire pour générer le objet, la syntaxe est sensible au contexte des accolades. À part ça, c'est la même chose que type_info . Personnellement, je ne pense pas que l'absence d'un mot-clé rend "plus hacky". Un peu plus surprenant, peut-être, mais rappelez-vous que l'objectif était de permettre la même syntaxe de calage-initialiseur qui était déjà permise pour les agrégats.

donc oui, vous pouvez probablement attendre plus de ce principe de conception à l'avenir:

  • si d'autres occasions se présentent où il est possible d'introduire de nouvelles fonctionnalités, sans de nouveaux mots-clés, puis le comité.
  • si de nouvelles caractéristiques nécessitent des types complexes, ces types seront placés dans std plutôt que sous forme de builtins.

D'où:

  • si une nouvelle fonctionnalité nécessite un type complexe et peut être introduite sans nouveaux mots-clés, alors vous obtiendrez ce que vous avez ici, qui est la syntaxe "core language" sans aucun nouveau mots-clés et qui utilise les types de bibliothèque de std .

je pense qu'il n'y a pas de division absolue en C++ entre le" langage de base " et les bibliothèques standards. Ce sont des chapitres différents dans la norme, mais chacun fait référence à l'autre, et il en a toujours été ainsi.

il y a une autre approche en C++11, qui est que lambdas introduire des objets qui ont anonymes types généré par le compilateur. Parce qu'ils n'ont pas de noms, ils ne sont pas du tout dans un espace-nom, certainement pas dans std . Ce n'est pas une approche appropriée pour les listes d'initialiseur, cependant, parce que vous utilisez le nom de type lorsque vous écrivez le constructeur qui en accepte un.

47
répondu Steve Jessop 2013-03-04 15:13:58

le Comité Standard c++ semble préférer ne pas ajouter de nouveaux mots-clés, probablement parce que cela augmente le risque de casser le code existant (le code d'héritage pourrait utiliser ce mot-clé comme le nom d'une variable, d'une classe, ou quoi que ce soit d'autre).

de plus, il me semble que définir std::initializer_list comme un conteneur tempéré est un choix assez élégant: si c'était un mot-clé, comment accéderiez-vous à son type sous-jacent? Comment voulez-vous parcourir? Vous auriez besoin d'un tas de de nouveaux opérateurs aussi, et cela vous forcerait simplement à vous souvenir de plus de noms et de plus de mots-clés pour faire les mêmes choses que vous pouvez faire avec les conteneurs standard.

traiter un std::initializer_list comme tout autre conteneur vous donne l'occasion d'écrire le code générique qui fonctionne avec l'une de ces choses.

mise à jour:

Alors, pourquoi introduire un nouveau type, au lieu d'utiliser une combinaison de existant? (tiré des commentaires)

pour commencer, tous les autres conteneurs ont des méthodes pour ajouter, enlever et mettre en place des éléments, qui ne sont pas souhaitables pour une collection générée par compilateur. La seule exception est std::array<> , qui enveloppe un tableau de style C de taille fixe et resterait donc le seul candidat raisonnable.

However, as Nicol Bolas fait remarquer à juste titre dans les commentaires, une autre différence fondamentale entre std::initializer_list et tous les autres conteneurs standard (y compris std::array<> ) est que ces derniers ont valeur sémantique , tandis que std::initializer_list a référence sémantique . Copier un std::initializer_list , par exemple, ne provoquera pas une copie des éléments qu'il contient.

en outre (encore une fois, courtoisie de Nicol Bolas), ayant un récipient spécial pour brace - listes d'initialisation permet de surcharger la façon dont l'utilisateur effectue l'initialisation.

42
répondu Andy Prowl 2017-05-23 10:31:02

ce n'est pas nouveau. Par exemple, for (i : some_container) s'appuie sur existence de méthodes spécifiques ou de fonctions autonomes dans la classe some_container . C# s'appuie encore plus sur ses bibliothèques .NET. En fait, je pense que c'est une solution assez élégante, parce que vous pouvez rendre vos cours compatibles avec certaines structures linguistiques sans compliquer les spécifications linguistiques.

6
répondu Spook 2013-03-04 10:02:37

ce n'est en effet rien de nouveau et combien ont souligné, cette pratique était là en C++ et est là, disons, en C#.

Andrei Alexandrescu a mentionné un bon point à ce sujet cependant: vous pouvez penser à lui comme une partie de l'Espace-nom "de base" imaginaire, alors il fera plus de sens.

donc, c'est quelque chose comme: core::initializer_list , core::size_t , core::begin() , core::end() et ainsi de suite. C'est juste une coïncidence malheureuse que std namespace a quelques constructions de langage de base à l'intérieur.

4
répondu Artem Tokmakov 2013-03-07 03:53:14

non seulement il peut fonctionner complètement dans la bibliothèque standard. L'Inclusion dans la bibliothèque standard ne signifie pas que le compilateur ne peut pas jouer des trucs astucieux.

bien qu'il puisse ne pas être en mesure dans tous les cas, il peut très bien dire: ce type est bien connu, ou un type simple, permet d'ignorer le initializer_list et juste avoir une image de mémoire de ce que la valeur initialisée devrait être.

En d'autres termes int i {5}; peut être équivalent à int i(5); ou int i=5; ou même intwrapper iw {5};intwrapper est une simple classe wrapper sur un int avec un trivial constructeur prenant un initializer_list

2
répondu Paul de Vrieze 2013-03-08 16:48:38

il ne fait pas partie du langage de base parce qu'il peut être mis en œuvre entièrement dans la bibliothèque, juste la ligne operator new et operator delete . Quel avantage y aurait-il à rendre les compilateurs plus compliqués à construire?

1
répondu Pete Becker 2013-03-04 13:35:28