65 votes

Comment boost :: variante et boost :: any work?

Comment faire de la variante et de la bibliothèque boost de travail à l'interne? Dans un projet sur lequel je travail, j'utilise actuellement marqués de l'union. Je veux utiliser autre chose, parce que les syndicats en C++ ne pas vous laisser utiliser des objets avec les constructeurs, destructeurs ou à une surcharge des opérateurs d'affectation.

J'ai interrogé la taille de tout et de variante, et fait quelques expériences avec eux. Dans mon programme, variante de la taille de la plus longue possible type plus 8 octets: je pense qu'il ma juste de 8 octets o le type d'informations et le reste étant de la valeur stockée. D'autre part, tout juste est 8 octets. Depuis que je suis sur une plate-forme 64 bits, je suppose que tout juste titulaire d'un pointeur.

Comment Tout savoir de quel type qu'elle détient? Comment Variante de réaliser ce qu'il fait par le biais de modèles? Je voudrais savoir davantage au sujet de ces classes avant de les utiliser.

78voto

Crazy Eddie Points 23778

Si vous lisez le boost::any documentation fournie à la source de l'idée: http://www.two-sdg.demon.co.uk/curbralan/papers/ValuedConversions.pdf

C'est de base se cacher de l'information, un élément essentiel C++ compétences à avoir. L'apprendre!

Depuis la plus haute voté réponse ici est totalement erronée, et j'ai des doutes que les gens vont effectivement aller chercher à la source pour vérifier ce fait, voici une base de mise en œuvre de l'un tout comme l'interface qui va encapsuler n'importe quel type avec une fonction f (), et lui permettre d'être appelé:

struct f_any
{
   f_any() : ptr() {}
   ~f_any() { delete ptr; }
   bool valid() const { return ptr != 0; }
   void f() { assert(ptr); ptr->f(); }

   struct placeholder
   {
     virtual ~placeholder() {}
     virtual void f() const = 0;
   };

   template < typename T >
   struct impl : placeholder
   {
     impl(T const& t) : val(t) {}
     void f() const { val.f(); }
     T val;
    };
   // ptr can now point to the entire family of 
   // struct types generated from impl<T>
   placeholder * ptr;

   template < typename T >
   f_any(T const& t) : ptr(new impl(t)) {}

  // assignment, etc...
};

boost::any fait la même chose, sauf que f() renvoie en fait typeinfo const& et fournit d'autres informations d'accès à la any_cast fonction de travail.

20voto

Michael Aaron Safyan Points 45071

La principale différence entre boost::any et boost::variant que any pouvez stocker tout type, tout en variant peut stocker qu'un seul d'un ensemble de types énumérés. L' any magasins de type un void* pointeur vers l'objet, ainsi que d'un typeinfo objet de rappeler le type sous-jacent et d'appliquer un certain degré de sécurité de type. En boost::variant, il calcule le maximum de la taille de l'objet, et utilise des "placement" pour allouer l'objet à l'intérieur de ce tampon. Il stocke également le type ou le type de l'index.

Notez que si vous avez Boost installé, vous devriez être en mesure de voir les fichiers source dans "tout.hpp" et "variante.hpp". Juste la recherche pour "inclure/boost/variante.hpp" et "include/boost/tout.hpp" dans "/usr", "/usr/local", et "/opt/local" jusqu'à ce que vous trouver les installés les en-têtes, et vous pouvez prendre un coup d'oeil.

Modifier
Comme cela a été souligné dans les commentaires ci-dessous, il y avait une légère imprécision dans ma description de boost::any. Bien qu'il puisse être mis en œuvre à l'aide de void* (et basé sur un modèle de détruire rappel de supprimer correctement le pointeur), actuellement mise en œuvre utilise any<T>::placeholder*, any<T>::holder<T> comme des sous-classes d' any<T>::placeholder pour unifier le type.

9voto

Tony D Points 43962

boost::any seulement des instantanés de l' typeinfo , tandis que le basé sur un modèle constructeur s'exécute: il a un pointeur vers un non-basé sur un modèle de la classe de base qui permet d'accéder à la typeinfo, et le constructeur dérivé d'un type spécifique de la classe de satisfaction que de l'interface. La même technique peut être utilisé pour capturer d'autres les fonctionnalités courantes d'un ensemble de types (par exemple, le streaming, la commune des opérateurs, des fonctions spécifiques), bien que le boost n'offre pas le contrôle de cette.

boost::variant est conceptuellement similaire à ce que vous avez fait avant, mais pas littéralement à l'aide d'un union et au lieu de prendre une approche manuelle de placement de la construction/destruction d'objets dans sa mémoire tampon (lors de la manipulation de l'alignement des questions explicitement), il travaille autour de l'restrictions que le C++ a re types complexes dans le réel unions.

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