|
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