Channels ▼
RSS

An Improved Variant Type Based on Member Templates


October 2000/An Improved Variant Type Based on Member Templates/Listing 4

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

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video