Boost logo

Boost :

From: Alexander Nasonov (alnsn-mycop_at_[hidden])
Date: 2003-02-19 05:11:16


Peter Dimov wrote:
> The other option is to support a dynamic_cast-style extract:
>
> T * p = extract<T*>(&var);
> T & r = extract<T&>(var);
>
> but it would likely require partial ordering/specialization.

I don't have access to a compiler with broken partial
ordering/specialization but I tried to keep it in mind when I implemented
extraction for dynamic_any. This code fragment is taken from
dynamic_any/any.hpp. Start reading from the bottom.

// T is not a class.
template<class T>
const T * extract_const_ptr(const placeholder * p, bool_id<false>)
{
  if(p == 0 || p->type(sig()) != typeid(T))
    return 0;
  typedef const nonclass_holder<T> holder_type;
  holder_type * ptr = static_cast<holder_type *>(p);
  return &ptr->value;
}

// T is a class.
template<class T>
const T * extract_const_ptr(const placeholder * p, bool_id<true>)
{
  return dynamic_cast<const T *>(p);
}

template<class T>
const T * extract_const_ptr(const placeholder * p, type_id<const T>)
{
  bool_id< ::boost::is_class<T>::value> id;
  return extract_const_ptr<T>(p, id);
}

// T is not a class.
template<class T>
T * extract_nonconst_ptr(placeholder * p, bool_id<false>)
{
  if(p == 0 || p->type(sig()) != typeid(T))
    return 0;
  typedef nonclass_holder<T> holder_type;
  holder_type * ptr = static_cast<holder_type *>(p);
  return &ptr->value;
}

// T is a class.
template<class T>
T * extract_nonconst_ptr(placeholder * p, bool_id<true>)
{
  return dynamic_cast<T *>(p);
}

template<class T>
T * extract_nonconst_ptr(placeholder * p, type_id<T>)
{
  bool_id< ::boost::is_class<T>::value> id;
  return extract_nonconst_ptr<T>(p, id);
}

// T is const.
template<class T>
T * extract_ptr(const placeholder * p, bool_id<true>)
{
  return extract_const_ptr(p, type_id<T>());
}

// T is not const.
template<class T>
T * extract_ptr(placeholder * p, bool_id<false>)
{
  return extract_nonconst_ptr(p, type_id<T>());
}

// Placeholder is 'placeholder' or 'const placeholder'.
template<class T, class Placeholder>
T * extract_ptr(Placeholder * p)
{
  bool_id< ::boost::is_const<T>::value> id;
  // Note to users: if you get compile error here then you are trying
  // to extract non-const pointer or reference from const 'any'.
  return extract_ptr<T>(p, id);
}

template<class T, class Placeholder>
T & extract_ref(Placeholder * p, type_id<T &>)
{
  if(T * ptr = extract_ptr<T>(p))
    return *ptr;
  throw bad_extract();
}

// T is a reference.
template<class T, class Placeholder>
T extract(Placeholder * p, bool_id<true>)
{
  return extract_ref(p, type_id<T>());
}

// T is not a reference.
template<class T, class Placeholder>
T extract(Placeholder * p, bool_id<false>)
{
  return extract_ref(p, type_id<const T &>());
}

template<class T, class Placeholder>
T extract(Placeholder * p)
{
  bool_id< ::boost::is_reference<T>::value> id;
  return extract<T>(p, id);
}

-- 
Alexander Nasonov
Remove -mycop from my e-mail address for timely response

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk