Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do boost::variant and boost::any work?

How do variant and any from the boost library work internally? In a project I am working on, I currently use a tagged union. I want to use something else, because unions in C++ don't let you use objects with constructors, destructors or overloaded assignment operators.

I queried the size of any and variant, and did some experiments with them. In my platform, variant takes the size of its longest possible type plus 8 bytes: I think it my just be 8 bytes o type information and the rest being the stored value. On the other hand, any just takes 8 bytes. Since i'm on a 64-bit platform, I guess any just holds a pointer.

How does Any know what type it holds? How does Variant achieve what it does through templates? I would like to know more about these classes before using them.

like image 338
salvador p Avatar asked Feb 14 '11 04:02

salvador p


People also ask

How does boost:: any work?

The key difference between boost::any and boost::variant is that any can store any type, while variant can store only one of a set of enumerated types. The any type stores a void* pointer to the object, as well as a typeinfo object to remember the underlying type and enforce some degree of type safety.

What is boost:: variant?

boost::variant is defined in boost/variant. hpp . Because boost::variant is a template, at least one parameter must be specified. One or more template parameters specify the supported types. In Example 24.1, v can store values of type double , char , or std::string .

What is boost any in C++?

The boost::any class (based on the class of the same name described in "Valued Conversions" by Kevlin Henney, C++ Report 12(7), July/August 2000) is a variant value type based on the second category. It supports copying of any value type and safe checked extraction of that value strictly against its type.

What is boost optional?

Boost C++ Libraries Class template optional is a wrapper for representing 'optional' (or 'nullable') objects who may not (yet) contain a valid value. Optional objects offer full value semantics; they are good for passing by value and usage inside STL containers. This is a header-only library.


2 Answers

If you read the boost::any documentation they provide the source for the idea: http://www.two-sdg.demon.co.uk/curbralan/papers/ValuedConversions.pdf

It's basic information hiding, an essential C++ skill to have. Learn it!

Since the highest voted answer here is totally incorrect, and I have my doubts that people will actually go look at the source to verify that fact, here's a basic implementation of an any like interface that will wrap any type with an f() function and allow it to be called:

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>(t)) {}    // assignment, etc... }; 

boost::any does the same basic thing except that f() actually returns typeinfo const& and provides other information access to the any_cast function to work.

like image 96
Edward Strange Avatar answered Sep 16 '22 14:09

Edward Strange


The key difference between boost::any and boost::variant is that any can store any type, while variant can store only one of a set of enumerated types. The any type stores a void* pointer to the object, as well as a typeinfo object to remember the underlying type and enforce some degree of type safety. In boost::variant, it computes the maximum sized object, and uses "placement new" to allocate the object within this buffer. It also stores the type or the type index.

Note that if you have Boost installed, you should be able to see the source files in "any.hpp" and "variant.hpp". Just search for "include/boost/variant.hpp" and "include/boost/any.hpp" in "/usr", "/usr/local", and "/opt/local" until you find the installed headers, and you can take a look.

Edit
As has been pointed out in the comments below, there was a slight inaccuracy in my description of boost::any. While it can be implemented using void* (and a templated destroy callback to properly delete the pointer), the actualy implementation uses any<T>::placeholder*, with any<T>::holder<T> as subclasses of any<T>::placeholder for unifying the type.

like image 39
Michael Aaron Safyan Avatar answered Sep 17 '22 14:09

Michael Aaron Safyan