How boost :: variant and boost :: any job?

How does an option and any of the boost libraries work internally? In the project I'm working on, I am currently using a tagged union. I want to use something else, because C ++ associations do not allow objects with constructors, destructors, or overloaded assignment operators.

I requested the size of any and option, and did some experimentation with them. On my platform, the option takes the size of its longest type plus 8 bytes: I think that it is only 8 bytes of type data, and the rest is a stored value. On the other hand, each of them takes only 8 bytes. Since I am on a 64-bit platform, I assume that any of them contains a pointer.

How does anyone know what type he holds? How does Option achieve what it does with templates? I would like to know more about these classes before using them.

+60
c ++ unions boost-variant boost-any
Feb 14 2018-11-11T00:
source share
3 answers

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

This is hiding basic information, a necessary C ++ skill. Learn it!

Since the highest voted answer here is completely incorrect, and I have doubts that people will really go look at the source to check this fact, here is the basic implementation of any such interface that will wrap any type with f () 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 :: anyone does the same basic thing, except that f () actually returns typeinfo const& and provides different access to information for any_cast function to work.

+72
Feb 14 '11 at 5:35
source share
— -

The key difference between boost::any and boost::variant is that any can store any type, and variant can only store one of the many types listed. Type any stores the void* pointer for an object, as well as a typeinfo object for remembering the base type and providing a certain degree of type safety. In boost::variant it computes the object of maximum size and uses the "placement of new" to highlight the object in this buffer. It also stores the type or type index.

Please note that if you have Boost installed, you can see the source files in "any.hpp" and "variant.hpp". Just find "include / boost / variant.hpp" and "include / boost / any.hpp" in "/ usr", "/ usr / local" and "/ opt / local" until you find the set headers and you can take a look.

Edit
As stated in the comments below, there was a slight inaccuracy in my description of boost :: any. Although it can be implemented using void* (and the template destroy the callback to delete the pointer correctly), the actual implementation uses any<T>::placeholder* , with any<T>::holder<T> as subclasses of any<T>::placeholder for type union.

+20
Feb 14 '11 at 5:00 a.m.
source share

boost::any just snapshots of typeinfo when the template constructor is running: it has a pointer to a non-templated base class that provides access to typeinfo, and the constructor displays a type class that satisfies this interface. The same technique can be used to capture other common features of a set of types (for example, streaming, common operators, certain functions), although boost does not provide control over this.

boost :: variant conceptually similar to what you did before, but do not literally use union and instead use a manual approach to creating / destroying objects in your buffer (when explicitly handling alignment problems) it works around the limitations that C ++ has complex types in real union s.

+9
Feb 14 '11 at 5:13
source share



All Articles