Boost logo

Boost :

From: Itay Maman (itay_maman_at_[hidden])
Date: 2002-06-28 05:03:15

It seems that the variant issue is very popular these days ... :)

The last couple of weeks I've been implementing a variant class
based on the ideas (which were, in large part, contributed by Doug
Gregor) discussed here in "Proposal --- a type safe union"

The main advantage of this variant implementation is the flexibility of
its visitor mechanism, which accepts 'standard' function objects. Having
this flexibility at hand, the implementation of other key-features (e.g:
recursive types) became fairly simple.

The source code (with two short programgs) is available at

Key points

- Supports construction and assignment from any of the types that the
variant can hold.

- Uses overload resolution rules for construction, assignment, and

- Can be visited by any function object. Performs compile-time check to
make sure the given function object can accept any of the possible types.

- Supports construction/assignment from variants with a different list
of types.

- Supports holding of incomplete types.

- Recursive types are allowed via incomplete types.

- (Exception safe) value semantics.

- Uses stack-based storage technique.

- Variant to variant assignment is (internally) carried out thru

- Does not use dynamic_cast's nor typeid()'s

* This implementation can use either mpl::list or Loki::Typelist for
manipulating types, determined by the USE_LOKI_SEQ preprocessor symbol.
The macros TYPE_SEQ_1 .. TYPE_SEQ_10 are used to instantiate the proper

* I tried to work with mpl but the compilation times were painfully
slow. I did read the other day, that the latest mpl code does solve this
problem, but didn't get to check it out, yet.

* The code hasn't been fully Boostified. It was tested on GCC 3.0.4, but
porting it to MSVC shouldn't be too difficult.

Feedback is welcome.


#include <iostream>
#include <boost/variant.hpp>

using boost::Variant;
using boost::Incomplete;
using std::cout;
using std::endl;

struct Add;
struct Sub;

typedef Variant<TYPE_SEQ_3(int, Incomplete<Add>, Incomplete<Sub> ) > Expr;

struct Add
    Add() { }
    Add(const Expr& l, const Expr& r) : lhs_(l), rhs_(r) { }
    Add(const Add& other) : lhs_(other.lhs_), rhs_(other.rhs_) { }

    Expr lhs_;
    Expr rhs_;

struct Sub
    Sub() { }
    Sub(const Expr& l, const Expr& r) : lhs_(l), rhs_(r) { }
    Sub(const Sub& other) : lhs_(other.lhs_), rhs_(other.rhs_) { }

    Expr lhs_;
    Expr rhs_;

struct Calculator
    Calculator() : result_(0) { }

    void operator()(Add& x) const
       result_ = x.lhs_(Calculator()).result_ +

    void operator()(Sub& x) const
       result_ = x.lhs_(Calculator()).result_ -

    void operator()(Expr& x) const
       result_ = x(Calculator()).result_;

    void operator()(int x) const
       result_ = x;

    mutable int result_;

}; // Calculator

int main(int argc, char *argv[])
    argc = argc;
    argv = argv;

    int n = 13;

    // e1: n + (40+2)-(10+14) = n+28
    Expr e1( Add(n, Sub(Add(40,2),Add(10,4))) );

    //Evaluate expression
    int res = e1(Calculator()).result_;
    cout << "result = " << res << endl;

    assert(res == n + 28);
    return 0;

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