1 // Copyright Daniel Wallin 2009. Use, modification and distribution is
2 // subject to the Boost Software License, Version 1.0. (See accompanying
3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 #ifndef LUABIND_INHERITANCE_090217_HPP
6 # define LUABIND_INHERITANCE_090217_HPP
13 # include <luabind/typeid.hpp>
14 # include <boost/scoped_ptr.hpp>
16 namespace luabind
{ namespace detail
{
18 typedef void*(*cast_function
)(void*);
19 typedef std::size_t class_id
;
21 class_id
const unknown_class
= (std::numeric_limits
<class_id
>::max
)();
25 class LUABIND_API cast_graph
31 // `src` and `p` here describe the *most derived* object. This means that
32 // for a polymorphic type, the pointer must be cast with
33 // dynamic_cast<void*> before being passed in here, and `src` has to
35 std::pair
<void*, int> cast(
36 void* p
, class_id src
, class_id target
37 , class_id dynamic_id
, void const* dynamic_ptr
) const;
38 void insert(class_id src
, class_id target
, cast_function cast
);
42 boost::scoped_ptr
<impl
> m_impl
;
45 // Maps a type_id to a class_id. Note that this actually partitions the
46 // id-space into two, using one half for "local" ids; ids that are used only as
47 // keys into the conversion cache. This is needed because we need a unique key
48 // even for types that hasn't been registered explicitly.
49 class LUABIND_API class_id_map
54 class_id
get(type_id
const& type
) const;
55 class_id
get_local(type_id
const& type
);
56 void put(class_id id
, type_id
const& type
);
59 typedef std::map
<type_id
, class_id
> map_type
;
63 static class_id
const local_id_base
;
66 inline class_id_map::class_id_map()
67 : m_local_id(local_id_base
)
70 inline class_id
class_id_map::get(type_id
const& type
) const
72 map_type::const_iterator i
= m_classes
.find(type
);
73 if (i
== m_classes
.end() || i
->second
>= local_id_base
)
78 inline class_id
class_id_map::get_local(type_id
const& type
)
80 std::pair
<map_type::iterator
, bool> result
= m_classes
.insert(
81 std::make_pair(type
, 0));
84 result
.first
->second
= m_local_id
++;
86 assert(m_local_id
>= local_id_base
);
88 return result
.first
->second
;
91 inline void class_id_map::put(class_id id
, type_id
const& type
)
93 assert(id
< local_id_base
);
95 std::pair
<map_type::iterator
, bool> result
= m_classes
.insert(
96 std::make_pair(type
, 0));
100 || result
.first
->second
== id
101 || result
.first
->second
>= local_id_base
104 result
.first
->second
= id
;
110 class_rep
* get(class_id id
) const;
111 void put(class_id id
, class_rep
* cls
);
114 std::vector
<class_rep
*> m_classes
;
117 inline class_rep
* class_map::get(class_id id
) const
119 if (id
>= m_classes
.size())
121 return m_classes
[id
];
124 inline void class_map::put(class_id id
, class_rep
* cls
)
126 if (id
>= m_classes
.size())
127 m_classes
.resize(id
+ 1);
131 template <class S
, class T
>
134 static void* execute(void* p
)
136 return static_cast<T
*>(static_cast<S
*>(p
));
140 template <class S
, class T
>
143 static void* execute(void* p
)
145 return dynamic_cast<T
*>(static_cast<S
*>(p
));
149 // Thread safe class_id allocation.
150 LUABIND_API class_id
allocate_class_id(type_id
const& cls
);
153 struct registered_class
155 static class_id
const id
;
159 class_id
const registered_class
<T
>::id
= allocate_class_id(typeid(T
));
162 struct registered_class
<T
const>
163 : registered_class
<T
>
166 }} // namespace luabind::detail
168 #endif // LUABIND_INHERITANCE_090217_HPP