Boost logo

Boost :

From: Jaap Suter (j.suter_at_[hidden])
Date: 2003-10-27 02:49:18

First of all, my apologies for the double posts. I'm not sure what caused my
Outlook to send it four times.

> I plan to eventually support something like the following:
> boost::variant< foo,bar > v( inplace<foo>(...) );
> v = inplace<bar>(...);

Looks perfect to me. Thanks.

> > Do all of your state types have nothrow constructors? If the call to
> > v.construct<T>(args)
> > is calling a nothrow constructor, then the "destroy, then create"
> > ordering can still preserve the strong guarantee, it seems.

Yes, they all have nothrow constructors. In fact, I'm working in an embedded
environment with exceptions disabled in release builds.

> Variant provides the basic guarantee for assignment lhs = rhs by copying
> the content of lhs onto the heap before its destruction. Then the
> content of rhs is copied to the storage of lhs. In the event of success,
> the backup is destroyed; in the event of an exception, the lhs variant
> stores a pointer to the backup and "redirects" all visitation requests
> accordingly.

I must admit that I have not looked at the implementation, nor at the most
recent version of the documentation, but this behaviour is new to me. I
thought the double-storage technique was still used in case there was not at
least one no-throw copy-constructible bounded-type in the variant (possibly
being boost::empty). I don't want to bring up the old discussion again, but
I'm wondering whether the above heap-allocation occurs even if the variant
consists solely of non-throwing types. This would render it unusable for me,
as I cannot allow allocations in all situations.

> So from an exception-safety point of view, it really doesn't matter too
> much whether Jaap's state types have nothrow constructors or not. The
> only difference will be that variant will avoid heap backup if any of
> the types are nothrow default-constructible. (Or if all of the types are
> nothrow copy-constructible, but that doesn't apply in this case.)

So can I assume Boost.Variant can detect non-throwability and act
accordingly (not do an allocation if not necessary)?

Brian does bring up another point, which is the order of destruction and
construction. Is this garantueed, or merely a consequence of the current
implementation scheme? Is it possible to make the order of dtor and
(copy-)ctor an explicitly document feature that can be relied upon?

On a related note, is it garantueed that the order of types in a given
sequence (for variant) corresponds with the order of the different
which-indices of the variant? In other words, if I pass in list<float, int,
bool> is it garantueed that which() returns 0 for float, 1 for int and 2 for
bool? Perhaps even better, is it possible to provide a nested template in
variant that allows me to do the following:

typedef variant<float, int, bool> my_variant;
int p = my_variant::which_for<float>::value; // p is 0, 1 or 2;
int q = my_variant::which_for<int>::value; // q is 0, 1 or 2 and not p;
int r = my_variant::which_for<int>::value; // r is 0, 1 or 2 and not p
nor q;
int w = my_variant::which_for<char>::value; // possibly compile error, but
preferably w is -1 indicating it's not in this variant.


Jaap Suter

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