Our version of variant class will expose the following interface:

template<typename TLIST>
class variant {
public:
   // default constructor - requires the first type
   // in the typelist to be default-constructible
   variant(void);

   // generic constructor - accepting one of predefined types
   template<typename T>
   variant(const T& t);

   // copy constructor
   variant(const variant<TLIST>& v);

   // assignment operators (using "variant" or "T" similarly to constructors) ...

   // destructor - makes sure to call destructor if non-trivial type is currenlty assigned
   ~variant(void);

   // getting the value out of variant (the type must be known,
   // otherwise exception will be thrown)
   template<typename T>
   T & get(void) ;

   // sending value to output (all types used must support operator<<)
   friend std::ostream & operator<<(std::ostream &out, const variant<TLIST> &v);
}; 


Minimalistic interface indeed. But understanding this basic version will give you a clue how more advanced features can be implemented.
We can use this class in following ways:

class Integer { /* trivial implementation, prints messages on construction/destruction */ };

void test_variant(void) {
   typedef TYPELIST_4(int, std::string, double, Integer) var_tlist;
   typedef variant<var_tlist> my_variant;

   my_variant v0;
   my_variant v1(10);
   my_variant v2(std::string("hello"));
   my_variant v3(Integer(5));
   my_variant v4(v3);
   my_variant v5 = 11;

   std::cout << "Initial values: v0="<<v0 << ", v1="<< v1
                << ", v2="<< v2 << ", v3="<<v3 << ", v4="<<v4 << std::endl;

   v4 = v2;
   v2 = 15;

   std::cout << "Values after assingment: v0="<<v0 << ", v1="<< v1
                << ", v2="<< v2 << ", v3="<<v3 << ", v4="<<v4 << std::endl;

   int i = v1.get<int>();
   std::cout << "Retrieved <int> from v1: " << i << std::endl;

   try {
      double d = v1.get<double>();
   } catch (std::bad_cast &e) {
      std::cout << "Failed to get <double> from v1 - bad_cast exception: " << e.what() << std::endl;
   }
} 

// The output: 
/*
Integer ctor
Integer copy ctor
Integer dtor
Integer copy ctor
Initial values: v0=0, v1=10, v2=hello, v3=5, v4=5
Integer dtor
Values after assingment: v0=0, v1=10, v2=15, v3=5, v4=hello
Retrieved <int> from v1: 10
Failed to get <double> from v1 - bad_cast exception: This variant does not hold requested type
Integer dtor
*/

Last edited Nov 30, 2007 at 8:38 PM by migo, version 1

Comments

No comments yet.