Listing 4: The final variant_t definition

#ifndef VARIANT_H
#define VARIANT_H

class variant_t
{
  public :

   variant_t() : data ( NULL ) {}
   variant_t( const variant_t & rhs )
     { if ( rhs.data != NULL )
         rhs.data->AddRef() ;
       data = rhs.data ;
     }
  ~variant_t()
     { if ( data != NULL )
         data->Release() ;
     }
   // NOTE: This code takes care of self-asignment.
   // DO NOT CHANGE THE ORDER of the statements.
   variant_t& operator = ( const variant_t& rhs )
     {
       if ( rhs.data != NULL )
         rhs.data->AddRef();
       if ( data != NULL )
         data->Release();
       data = rhs.data ;
       return * this ;
     }

  // This member template constructor allows you to
  // instance a variant_t object with a value of any type.
  template<typename T> variant_t ( T v )
    : data ( new Impl<T>(v) )
    { data->AddRef() ; }

  // This generic conversion operator let you retrieve
  // the value held. To avoid template specialization conflicts,
  // it returns an instance of type T, which will be a COPY
  // of the value contained.
  template<typename T> operator T () const
    { return CastFromBase<T>( data )->data ; }

  // This forms returns a REFERENCE and not a COPY, which
  // will be significant in some cases.
  template<typename T> const T & get() const
    { return CastFromBase<T>( data )->data ; }

  template<typename T> bool is_type() const
    { return typeid(*data)==typeid(Impl<T>); }

  template<typename T> bool is_type(T v) const
    { return typeid(*data)==typeid(v); }

  private :

    struct ImplBase
    {
      ImplBase() : refs ( 0 ) {}
      virtual ~ImplBase() {}
      void AddRef () { refs ++ ; }
      void Release() { refs -- ;
                       if ( refs == 0 )
                         delete this ;
                     }
      size_t refs ;
    } ;

    template<typename T>
    struct Impl : ImplBase
    {
       Impl ( T v ) : data ( v ) {}
      ~Impl () {}
      T data ;
    } ;

    // The following method is static because it doesn't
    // operate on variant_t instances.
    template<typename T>
    static Impl<T>* CastFromBase ( ImplBase* v )
    {
      // This upcast will fail if T is other than the T used
      // with the constructor of variant_t.
      Impl<T>* p = dynamic_cast<Impl<T>*> ( v ) ;
      if ( p == NULL )
        throw invalid_argument
         ( typeid(T).name()+string(" is not a valid type"));
      return p ;
    }

    ImplBase* data ;
} ;

#endif