Boost logo

Boost :

From: Itay (itay_maman_at_[hidden])
Date: 2002-06-08 04:44:16


I'd like to propose a type-safe union library (aka: variant, discriminated
union). The general concept has been thoroughly described by Andrei
Alexandrescu at http://oonumerics.org/tmpw01/alexandrescu.pdf . My
suggested class, Super_union, does not require RTTI to work properly, as all
the important details are handled by compile-time algorithms.

Here is the general scheme:

Super_union is parameterized on a type-list of its 'legal' types (TypeList).
It uses a boost::any-like data member to hold its assigned value.
Additionally, it uses an integer data member (called: tid_) to identify the
type of the held value. The mapping of types to integers is done by using
the 'index_of' type-list algorithm. Super_union's constructors make sure
tid_ is always kept in-sync with the concrete type of the held value.

Extracting a Super_union held value is done thru visitation: Super_union's
dedicated visitor (Super_union::Visitor) is aware of the visited union's
type-list, and is parameterized on an 'OnVisit' policy, which specifies its
concrete visit behavior. Basically, Super_union::Visitor uses the tid_ value
to find the corresponding type from the TypeList and then uses static_cast
to extract the held value.
To make this process work at run-time, the 'vtable' idiom (again, described
by Andrei), is used : tid_ is used as an index into a table of pointers to
functions. Each such function takes care of doing its appropriate cast, and
of passing the extracted value back to the visitor.

A few key points:
1) dynamic_cast() is not needed at all.
2) The business of storing the held value (currently done by boost::any) can
be factored out into a storage policy. Hence: Other (possibly faster)
generic storage techniques can be used.
3) The required type-list functionality is minor: length, index_of, type_at.
These 3 algorithms can be re-implemented without partial template
specialization, so the whole thing is compatible with MSVC

Any comments are welcome.

-Itay

Usage
-----

struct size_visit {
   size_visit() : total_(0) { }

   template<class Visitor, class Value>
   void visit_at(Visitor& , const Value& value)

      total_ += sizeof(value);
   }

   int total_;

}; // size_visit

int main(int argc, char* argv[]) {

   typedef TYPELIST_5(Class_a, const char*, int, double, std::string)
The_list;

   typedef Super_union<The_list> Concrete_union;
   Concrete_union u0;

   Concrete_union::Visitor<size_visit>::type size_visitor;

   u0 = 4.95;
   size_visitor.go(u0);

   u0 = std::string("Worldcup");
   size_visitor.go(u0);

   cout << "total size = " << size_visitor.total_ << '\n';

   return 0;
}


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