Boost logo

Boost :

From: Eric Friedman (ebf_at_[hidden])
Date: 2003-09-19 15:28:47


Boosters,

In the past several weeks, I've worked on "finishing" the interface and
implementation of boost::variant. Before spending significant effort on
updating the documentation to reflect these changes, I'd like to first
ensure everyone is satisfied with the current state of the library.

---
Interface:
1) Simple recursive variant types are now easily generated. For example,
  typedef boost::recursive_variant<
      int
    , std::vector< boost::recursive_variant_ >
    >::type my_recursive_variant;
Of course, "manual" recursive variants may be generated using
recursive_wrapper (originally boost::incomplete). That is,
  struct my;
  typedef boost::variant<
      int
    , boost::recursive_wrapper<my>
    > my_recursive_variant;
  struct my
  {
    my_recursive_variant var;
    // ...
  };
2) Reference content is now fully supported, including support for
inheritance hierarchies. That is,
  Derived d;
  boost::variant<Base&> b(d);
  assert( boost::get<Base>(&b) == &d );
will work as indicated, and will not slice d.
---
Implementation:
The "controversial" double storage technique is now disabled if the first
bounded type is nothrow default-constructible (as detected by
has_nothrow_constructor). For example, boost::variant<boost::empty, ...>
will never use double storage. In the event of the failure of an operation,
the first bounded type will be default constructed, leaving variant with a
meaningful state. Thus operations on variant always guarantee at least the
basic guarantee.
For now, I think the double storage implementation should remain, with the
above ability to disable it. Further, if every bounded type of variant is
nothrow copy-constructible, the double storage technique will similarly be
disabled. In the advent of a Boost.Move library, this will be extended as
well to all types that are nothrow "move-constructible."
Thus, I have not adopted David Abrahams's proposal to use dynamic allocation
to generally ensure variant's basic guarantee (instead of double storage),
as described in http://aspn.activestate.com/ASPN/Mail/Message/1789195. I'm a
bit wary of this approach, as it complicates variant's exception
specifications (operations may now throw std::bad_alloc), and while it
eliminates the space inefficiency of double storage, it introduces the many
inefficiencies associated with dynamic allocation. In short, it is not clear
to me that such an approach is in fact "better" (or worse) than the current
approach.
I'd appreciate feedback on any of this.
Thanks,
Eric

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