93 votes

Pourquoi isn ' t std::initializer_list un langage intégré ?

Pourquoi n'est-ce pas std::initializer_list d'un noyau de langue intégré?

Il me semble que c'est une caractéristique importante de C++11 et pourtant, il ne dispose pas de son propre mot clé réservé (ou quelque chose de semblable).

Au lieu de cela, initializer_list c'est juste un modèle de classe à partir de la bibliothèque standard qui a une spéciale, l'implicite de la cartographie de la nouvelle - calé-init-liste {...} de syntaxe qui sont gérées par le compilateur.

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

Est-ce la façon dont les nouveautés du langage C++ sera maintenant mis en œuvre: par rôles implicites de certaines classes de modèle et non par la base de la langue?


Veuillez tenir compte de 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 de 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 classique de tableau, vous pouvez probablement ajouter const ici et là
  2. trois points existent déjà dans la langue (var-args, maintenant variadic templates), pourquoi ne pas ré-utiliser la syntaxe (et lui faire sentir intégré)
  3. juste un conteneur existant, pourrait ajouter const et &

Tous d'entre eux sont déjà une partie de la langue. J'ai seulement écrit mes 3 premières idées, je suis sûr qu'il ya beaucoup d'autres approches.

48voto

Steve Jessop Points 166970

Il y avait déjà des exemples de "base" des fonctionnalités de langage qui est retourné types définis dans l' std d'espace de noms. typeid retours std::type_info et (étirement d'un point peut-être) sizeof retours std::size_t.

Dans le premier cas, vous avez déjà besoin d'inclure un en-tête standard pour l'utilisation de cette soi-disant "langage de base".

Maintenant, pour l'initialiseur de listes, il arrive qu'aucun mot-clé est nécessaire pour générer l'objet, la syntaxe est sensible au contexte des accolades. À part que c'est le même que type_info. Personnellement, je ne pense pas que l'absence d'un mot clé permet de "plus hacky". Un peu plus surprenant, peut-être, mais n'oubliez pas que l'objectif était de permettre le même arc-boutée-initialiseur de syntaxe qui a déjà permis d'agrégats.

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

  • si plus d'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 fonctionnalités nécessitent des types complexes, ces types de être placé dans std plutôt que comme des objets internes.

Donc:

  • si une nouvelle fonctionnalité nécessite un type complexe et peut être introduit sans de nouveaux mots-clés, puis vous obtiendrez ce que vous avez ici, qui est "la base de la langue" syntaxe, pas de nouveaux mots-clés et qui utilise la bibliothèque de types de std.

Ce qui, je pense, c'est qu'il n'est pas absolue division en C++ entre le "langage de base" et les bibliothèques standard. Ils sont différents chapitres de la norme, mais que chacune des références de l'autre, et il en a toujours été ainsi.

Il y a une autre approche dans le C++11, qui est que les 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 dans un espace de noms à tous, et certainement pas en std. Ce n'est pas une approche appropriée pour l'initialiseur listes, bien que, parce que vous utilisez le nom de type, lorsque vous écrivez un constructeur qui accepte un.

42voto

Andy Prowl Points 62121

La Norme C++ Comité semble préférer ne pas ajouter de nouveaux mots clés, probablement parce que cela augmente le risque de casser le code existant (ancien code pourrait utiliser ce mot-clé comme le nom d'une variable, d'une classe, ou tout autre chose).

Par ailleurs, il me semble que la définition d' std::initializer_list que basé sur un modèle de récipient est un choix élégant: si c'était un mot-clé, comment voulez-vous accéder à son type sous-jacent? Comment voulez-vous parcourir? Vous auriez besoin d'un tas de nouveaux opérateurs, et qu'il serait juste de vous forcer à se rappeler plus de noms et de mots-clés plus à faire les mêmes choses que vous pouvez faire avec des conteneurs standard.

Le traitement d'un std::initializer_list comme tout autre récipient vous donne l'opportunité d'écrire le code générique qui fonctionne avec n'importe quel de ces choses.

Mise à JOUR:

Alors pourquoi introduire un nouveau type, au lieu d'utiliser une combinaison de l'existant? (d'après les commentaires)

Pour commencer, tous les autres conteneurs ont des méthodes pour l'ajout, la suppression et emplacing éléments, qui ne sont pas souhaitables pour un générées par le compilateur de la collection. La seule exception est - std::array<>, qui s'enroule une taille fixe C-gamme de style et ne seraient donc pas la seule raisonnable candidat.

Cependant, comme Nicol Bolas correctement points dans les commentaires, un autre, la différence fondamentale entre l' std::initializer_list et tous les autres types de conteneurs (y compris les std::array<>) est que ces derniers ont une valeur sémantique, alors que std::initializer_list a référence sémantique. La copie d'un std::initializer_list, par exemple, de ne pas provoquer une copie des éléments qu'il contient.

De plus (une fois de plus, avec l'aimable autorisation de Nicol Bolas), avoir un conteneur spécial pour corset-initialisation des listes permet la surcharge sur la façon dont l'utilisateur est l'exécution de l'initialisation.

6voto

Spook Points 11276

Ce n’est rien de nouveau. Par exemple, s’appuie sur l' [existence de méthodes spécifiques ou des fonctions autonomes](http://www.cprogramming.com/c++11/c++11-ranged-for-loop.html) en classe. C# même repose encore plus sur ses bibliothèques .NET. En fait, je pense, que c’est tout à fait une solution élégante, parce que vous pouvez faire vos classes compatibles avec certaines structures de la langue sans compliquer la spécification du langage.

4voto

biocomp Points 590

Rien de nouveau, et la façon dont beaucoup l'ont souligné, cette pratique était là, en C++, et est-il, par exemple, en C#.

Andrei Alexandrescu a mentionné un bon point sur ce bien: Vous pouvez y penser comme à une partie de l'imaginaire "de base" de l'espace de noms, puis il va faire plus de sens.

Donc, c'est vraiment quelque chose comme: core::initializer_list, core::size_t, core::begin(), core::end() et ainsi de suite. C'est juste une coïncidence malheureuse qu' std de l'espace de noms a un certain langage de base des constructions à l'intérieur.

2voto

Paul de Vrieze Points 3715

Non seulement cela peut-il fonctionner complètement dans la bibliothèque standard. L'Inclusion dans la bibliothèque standard ne veut pas dire que le compilateur ne peut pas jouer à des trucs astucieux.

Il peut ne pas être en mesure de dans tous les cas, il peut très bien dire: ce type est bien connu, ou un type simple, permet d'ignorer l' initializer_list , et se contenter d'une mémoire image de ce que les initialisé la valeur doit être.

En d'autres mots, 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

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