
Hi Mathias, On Mon, Jun 29, 2009 at 11:51 PM, Mathias Gaunard < mathias.gaunard@ens-lyon.org> 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 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 [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; map.key<K0>(...).value<V0>(...) ... .key<Kn>(...).value<Vn>(...) ; Cheers, Christian [1] for every assignment when using a variant<T0..Tn> where any of Tn does not have a nothrow move or nothrow default ctor.