Boost logo

Boost :

From: Andrei Alexandrescu (andrewalex_at_[hidden])
Date: 2002-06-25 16:55:23


Congratulations Eric for the great work. As I told you via email, the last
installment of the Discriminate Union series might be of some interest. See
http://cuj.com/experts/2008/alexandr.htm, which comes with downloadable
source code (ftp://ftp.cuj.com/pub/2002/2008/alexandr.zip). Among the more
interesting updates:

* eliminated the "unbounded" choice (see below on why)
* much more elegant (than before) and decoupled conversions through
visitation
* sophisticated Variant-to-Variant conversions (again through visitation)
that consistently yield "internal compiler error" on three compilers: gcc
2.95.2, MWCW 7.0, MSVC 7.1.

"Douglas Gregor" <gregod_at_[hidden]> wrote in message
news:200206242026.02965.gregod_at_cs.rpi.edu...

> 1) Why is it that the variant can be unbounded? I'm having a hard time
> justifying a variant type that contains a value that is probably one of
the
> specified types, but might be something else. Here's a nightmare scenario:
>
> typedef boost::variant<int, float, string>::unbounded<true>::type
MyVariant;
> // ...
>
> MyVariant v(3.14159); // think it's holding a float? nope...
>
> Bounding the variant completely has the wonderful property that many
uses of
> the variant can check for completeness of decoding. So I guess there are
two
> questions: why do we need the ability to unbound a variant, and how would
> this differ from the existing boost::any?

I agree with that. For that reason (and for simplicity of exposure) I
decided to rip unbounded support from Variant and leave that task to "any".
By the way, does anyone work on making "any" visitable?

> 2) Why use the vtable idiom when the variant is completely bounded? The
> vtables are quite a bit larger than the single byte needed to specify
which
> type of the variant is selected, and I don't see any benefit to the vtable
> approach.

That's true, but the benefit is much smaller than you might think. Alignment
would have the one-byte index occupy four bytes anyway, even if you put it
after the aligned storage. Very few classes have an size that's not a
multiple of 4. Besides, I believe (without having actually tested) that
speed might be affected as well.

> 3) I'd really like to see the ability to construct from a type convertible
to
> some value that the variant can store, e.g.,
>
> boost::variant<int, float, string> v(3.14159); // convert double to
float

Yes, that's easy to implement and a great boon. The Variant class in the
article does not implement that for simplicity, but hints about it in a
comment in the source code.

On a related note, looking at the implementation reinforces my impression
that programming with mpl is more trouble than it's worth. After including
13 (!) mpl headers, the net benefit is that more code must be written with
mpl than without. For example, computing the maximum sized type in a
typelist takes 26 non-blank lines, while the vanilla MaxSize takes 16 lines
to do the same task. I didn't run a full analysis, but my impression after a
couple of reads is that the difference in source file sizes (783 vs. 573
lines) is partly due to using mpl.

Changing gears again - I see this function:

 // swap_impl : Swaps using Koenig lookup but falls back to std::swap on
non-conforming compilers.
 template <typename T>
 void swap_impl(T& t1, T& t2)
 {
  using namespace std;
  swap(t1, t2);
 }

I've been corrected on clc++m that the correct version is:

 // swap_impl : Swaps using Koenig lookup but falls back to std::swap on
non-conforming compilers.
 template <typename T>
 void swap_impl(T& t1, T& t2)
 {
  using std::swap;
  swap(t1, t2);
 }

Is that true?

Anyhow - Eric, I think it would be worthwhile to change the code to use
visitation for conversion, it's much more elegant and doesn't have threading
issues (runtime initialization of the vtable is no longer necessary).

Andrei


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk