Subject: Re: [boost] Interest in a "Heterogenous Container" system?
From: Christian Schladetsch (christian.schladetsch_at_[hidden])
Date: 2009-06-29 18:12:07
On Mon, Jun 29, 2009 at 11:51 PM, Mathias Gaunard <
> Christian Schladetsch wrote:
> boost::variant doesnt support custom allocators. it uses naked new and
> variant stores objects within itself. If you declare a variant on the
> stack, your object lies on the stack.
> The temporary heap backup is only there in operator= and only when you
> don't have a nothrow move or nothrow default constructor on one of your
> And it's only used for a few instructions unless you throw anyway, so who
> cares about what allocator it uses.
The issue of which allocator to use is quite important to some people,
especially in embedded and/or high-performance situations. Sliding in a heap
allocation somewhere in a container which has an allocator is a big no-no.
ptr_container does it as well when making temporary arrays and for clones.
In the case of variant<> using the heap to make a backup, it may not seem
like such a big deal to some. But allocating and deallocating on the heap,
ignoring the containers allocator, for every assignment , is a
deal-breaker for others.
In any case (no pun intended), I've compared heterogenous::vector<> with
vector<any> and vector<variant> in http://tinyurl.com/larqyy.
The differences are:
* I had to modify any<> to add an allocator. See http://tinyurl.com/mxh9gm.
* vector<any<alloc<char> >, alloc<any<alloc<char> > > > is effectively
typeless. This means that anyone could add anything to such a vector, and as
such I think this is too lenient and error prone. Adding an object to a
vector<any> requires a copy. map<any, any> can't be implemented.
* vector<variant<T0, .. Tn>, alloc<variant<T0,...Tn> > requires all types
that could go into the container to be known at the point of declaration,
which is contrary to the idea of having a generic heterogenous container.
Adding an object to a vector<variant> also makes a copy and possibly an
allocation that does not use the containers allocator . map<variant<..>,
variant<...> > could make sense but it would be a lot of work and difficult
to maintain, as a variant<> with N types needs N*N comparison functions.
* heterogenous::vector<> requires that a type T added to the container must
derive at some point from heterogenous::common_base. This excludes adding
builtin types, and means that you either have to change your existing class
definitions to put them into such a container, or use a supplied
heterogenous::adaptor<T> system. Allowing the addition of builtin types, and
types not derived from common_base is certainly possible. However, I don't
think that would be a benefit. In that case, you may's well use vector<any<>
>. Adding an object to a heterogenous::container does not require a copy,
uses the correct allocator, and copies are also made using the correct
allocator. heterogenous::map<> can make sense with a single comparison
operator and a common custom base.
At this point, I'll go away and flesh out the idea more. Thanks to those
whom pointed out any and variant, but I think that vector<any> is too
lenient and vector<variant> is too restrictive, and both require copies to
insert. I don't see how associative containers can work with these, but I
can do it with heterogenous::map as in
typedef heterogenous:::map<my_less, my_base, my_alloc> map;
 for every assignment when using a variant<T0..Tn> where any of Tn does
not have a nothrow move or nothrow default ctor.