
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