Boost logo

Boost :

Subject: Re: [boost] Interest in a "Heterogenous Container" system?
From: Christian Schladetsch (christian.schladetsch_at_[hidden])
Date: 2009-06-29 18:12:07

Hi Mathias,

On Mon, Jun 29, 2009 at 11:51 PM, Mathias Gaunard <
mathias.gaunard_at_[hidden]> wrote:

> Christian Schladetsch wrote:
> boost::variant doesnt support custom allocators. it uses naked new and
>> delete.
> 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
> types.
> 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 [1], is a
deal-breaker for others.

In any case (no pun intended), I've compared heterogenous::vector<> with
vector<any> and vector<variant> in

The differences are:

* I had to modify any<> to add an allocator. See

* 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 [1]. 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;


[1] for every assignment when using a variant<T0..Tn> where any of Tn does
not have a nothrow move or nothrow default ctor.

Boost list run by bdawes at, gregod at, cpdaniel at, john at