os/ossrv/ossrv_pub/boost_apis/boost/python/object/inheritance.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright David Abrahams 2002.
sl@0
     2
// Distributed under the Boost Software License, Version 1.0. (See
sl@0
     3
// accompanying file LICENSE_1_0.txt or copy at
sl@0
     4
// http://www.boost.org/LICENSE_1_0.txt)
sl@0
     5
#ifndef INHERITANCE_DWA200216_HPP
sl@0
     6
# define INHERITANCE_DWA200216_HPP
sl@0
     7
sl@0
     8
# include <boost/python/type_id.hpp>
sl@0
     9
# include <boost/shared_ptr.hpp>
sl@0
    10
# include <boost/mpl/if.hpp>
sl@0
    11
# include <boost/type_traits/is_polymorphic.hpp>
sl@0
    12
# include <boost/type_traits/is_base_and_derived.hpp>
sl@0
    13
# include <boost/detail/workaround.hpp>
sl@0
    14
sl@0
    15
namespace boost { namespace python { namespace objects {
sl@0
    16
sl@0
    17
typedef type_info class_id;
sl@0
    18
using python::type_id;
sl@0
    19
sl@0
    20
// Types used to get address and id of most derived type
sl@0
    21
typedef std::pair<void*,class_id> dynamic_id_t;
sl@0
    22
typedef dynamic_id_t (*dynamic_id_function)(void*);
sl@0
    23
sl@0
    24
BOOST_PYTHON_DECL void register_dynamic_id_aux(
sl@0
    25
    class_id static_id, dynamic_id_function get_dynamic_id);
sl@0
    26
sl@0
    27
BOOST_PYTHON_DECL void add_cast(
sl@0
    28
    class_id src_t, class_id dst_t, void* (*cast)(void*), bool is_downcast);
sl@0
    29
sl@0
    30
//
sl@0
    31
// a generator with an execute() function which, given a source type
sl@0
    32
// and a pointer to an object of that type, returns its most-derived
sl@0
    33
// /reachable/ type identifier and object pointer.
sl@0
    34
//
sl@0
    35
sl@0
    36
// first, the case where T has virtual functions
sl@0
    37
template <class T>
sl@0
    38
struct polymorphic_id_generator
sl@0
    39
{
sl@0
    40
    static dynamic_id_t execute(void* p_)
sl@0
    41
    {
sl@0
    42
        T* p = static_cast<T*>(p_);
sl@0
    43
        return std::make_pair(dynamic_cast<void*>(p), class_id(typeid(*p)));
sl@0
    44
    }
sl@0
    45
};
sl@0
    46
sl@0
    47
// now, the non-polymorphic case.
sl@0
    48
template <class T>
sl@0
    49
struct non_polymorphic_id_generator
sl@0
    50
{
sl@0
    51
    static dynamic_id_t execute(void* p_)
sl@0
    52
    {
sl@0
    53
        return std::make_pair(p_, python::type_id<T>());
sl@0
    54
    }
sl@0
    55
};
sl@0
    56
sl@0
    57
// Now the generalized selector
sl@0
    58
template <class T>
sl@0
    59
struct dynamic_id_generator
sl@0
    60
  : mpl::if_<
sl@0
    61
        boost::is_polymorphic<T>
sl@0
    62
        , boost::python::objects::polymorphic_id_generator<T>
sl@0
    63
        , boost::python::objects::non_polymorphic_id_generator<T>
sl@0
    64
    >
sl@0
    65
{};
sl@0
    66
sl@0
    67
// Register the dynamic id function for T with the type-conversion
sl@0
    68
// system.
sl@0
    69
template <class T>
sl@0
    70
void register_dynamic_id(T* = 0)
sl@0
    71
{
sl@0
    72
    typedef typename dynamic_id_generator<T>::type generator;
sl@0
    73
    register_dynamic_id_aux(
sl@0
    74
        python::type_id<T>(), &generator::execute);
sl@0
    75
}
sl@0
    76
sl@0
    77
//
sl@0
    78
// a generator with an execute() function which, given a void*
sl@0
    79
// pointing to an object of type Source will attempt to convert it to
sl@0
    80
// an object of type Target.
sl@0
    81
//
sl@0
    82
sl@0
    83
template <class Source, class Target>
sl@0
    84
struct dynamic_cast_generator
sl@0
    85
{
sl@0
    86
    static void* execute(void* source)
sl@0
    87
    {
sl@0
    88
        return dynamic_cast<Target*>(
sl@0
    89
            static_cast<Source*>(source));
sl@0
    90
    }
sl@0
    91
        
sl@0
    92
};
sl@0
    93
sl@0
    94
template <class Source, class Target>
sl@0
    95
struct implicit_cast_generator
sl@0
    96
{
sl@0
    97
    static void* execute(void* source)
sl@0
    98
    {
sl@0
    99
        Target* result = static_cast<Source*>(source);
sl@0
   100
        return result;
sl@0
   101
    }
sl@0
   102
};
sl@0
   103
sl@0
   104
template <class Source, class Target>
sl@0
   105
struct cast_generator
sl@0
   106
  : mpl::if_<
sl@0
   107
        is_base_and_derived<Target,Source>
sl@0
   108
      , implicit_cast_generator<Source,Target>
sl@0
   109
      , dynamic_cast_generator<Source,Target>
sl@0
   110
    >
sl@0
   111
{
sl@0
   112
};
sl@0
   113
sl@0
   114
template <class Source, class Target>
sl@0
   115
inline void register_conversion(
sl@0
   116
    bool is_downcast = ::boost::is_base_and_derived<Source,Target>::value
sl@0
   117
    // These parameters shouldn't be used; they're an MSVC bug workaround
sl@0
   118
    , Source* = 0, Target* = 0)
sl@0
   119
{
sl@0
   120
    typedef typename cast_generator<Source,Target>::type generator;
sl@0
   121
sl@0
   122
    add_cast(
sl@0
   123
        python::type_id<Source>()
sl@0
   124
      , python::type_id<Target>()
sl@0
   125
      , &generator::execute
sl@0
   126
      , is_downcast
sl@0
   127
    );
sl@0
   128
}
sl@0
   129
sl@0
   130
}}} // namespace boost::python::object
sl@0
   131
sl@0
   132
#endif // INHERITANCE_DWA200216_HPP