$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
From: Scott Meyers (usenet_at_[hidden])
Date: 2006-03-10 14:41:30
It took me a little while to figure out that get<T> on a variant is really just 
the moral equivalent of dynamic_cast<T> with a funny syntax.  I'd like to 
understand why, given a variant v, this syntax is used
   T* p = get<T>(&v);
   T& r = get<T>(v);
instead of this:
   T* p = variant_cast<T*>(&v);
   T& r = variant_cast<T&>(v);
any_cast on pointers also uses what I consider to be a counterintuitive syntax, 
using this (for an any object a)
   T* p = any_cast<T>(&a)
instead of this:
   T* p = any_cast<T*>(&a)
However, any_cast to a reference works with a syntax analogous to dynamic_cast.
Implementing the "expected" syntax doesn't seem to be too difficult.  For 
example, here's my quick cut at variant_cast:
   template<typename T, typename U1, typename U2, typename U3>
   T variant_cast(boost::variant<U1, U2, U3>& v)          // ref
   {
     using namespace boost;
     BOOST_STATIC_ASSERT(is_reference<T>::value);
     return get<remove_reference<T>::type>(v);
   }
   template<typename T, typename U1, typename U2, typename U3>
   T variant_cast(const boost::variant<U1, U2, U3>& v)    //ref-to-const
   {
     using namespace boost;
     BOOST_STATIC_ASSERT(is_reference<T>::value);
     return get<remove_reference<T>::type>(v);
   }
   template<typename T, typename U1, typename U2, typename U3>
   T variant_cast(boost::variant<U1, U2, U3> *pv)         // ptr
   {
     using namespace boost;
     BOOST_STATIC_ASSERT(is_pointer<T>::value);
     return get<remove_pointer<T>::type>(pv);
   }
   template<typename T, typename U1, typename U2, typename U3>
   T variant_cast(const boost::variant<U1, U2, U3> *pv)   // ptr-to-const
   {
     using namespace boost;
     BOOST_STATIC_ASSERT(is_pointer<T>::value);
     return get<remove_pointer<T>::type>(pv);
   }
In a thread last month, Marc Mutz posted this approach to "normalizing" the 
syntax of any_cast:
     template <typename T> class any_cast2 : noncopyable {
         const any & m_any;
     public:
         explicit any_cast2( const any & v ) : m_any( v ) {}
         operator T() const { return any_cast<T>( m_any ); }
     };
     template <typename T> class any_cast2<T*> : noncopyable {
         any * const m_any;
     public:
         explicit any_cast2( any * v ) : m_any( v ) {}
         operator T * () const { return any_cast<T>( m_any ); }
     };
     template <typename T> class any_cast2<const T*> : noncopyable {
         const any * const m_any;
     public:
         explicit any_cast2( const any * v ) : m_any( v ) {}
         operator const T * () const { return any_cast<T>( m_any ); }
     };
     template <typename T> class any_cast2<T&> : noncopyable {
         any & m_any;
     public:
         explicit any_cast2( any & v ) : m_any( v ) {}
         operator T & () const { return any_cast<T&>( m_any ); }
     };
     template <typename T> class any_cast2<const T&> : noncopyable {
         const any & m_any;
     public:
         explicit any_cast2( const any & v ) : m_any( v ) {}
         operator const T & () const { return any_cast<const T&>( m_any ); }
     };
Maybe there are problems to these approaches -- I've hardly investigated them. 
But I would be interested to know if there is a good reason for the syntaxes for 
dynamic_cast, any_cast, and get to vary so much.
Thanks,
Scott