|
Boost Users : |
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
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net