cleanup
[luabind.git] / luabind / back_reference.hpp
blob01d28f11da182cdcc8612e6a786310f24c67621d
1 // Copyright (c) 2004 Daniel Wallin and Arvid Norberg
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the "Software"),
5 // to deal in the Software without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Software, and to permit persons to whom the
8 // Software is furnished to do so, subject to the following conditions:
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
14 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
15 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
18 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
23 #ifndef BACK_REFERENCE_040510_HPP
24 #define BACK_REFERENCE_040510_HPP
26 #include <luabind/lua_include.hpp>
27 #include <luabind/wrapper_base.hpp>
28 #include <boost/type_traits/is_polymorphic.hpp>
29 #include <boost/mpl/if.hpp>
31 namespace luabind {
33 #if !(defined(BOOST_MSVC) && BOOST_MSVC <= 1300)
34 template<class T>
35 T* get_pointer(T& ref)
37 return &ref;
40 namespace detail {
41 #else
42 namespace detail {
44 struct no_overload_tag {};
46 } // namespace detail
48 detail::no_overload_tag get_pointer(...);
50 namespace detail {
52 typedef char(&yes_overload)[1];
53 typedef char(&no_overload)[2];
55 no_overload check_overload(no_overload_tag);
56 template<class T>
57 yes_overload check_overload(T const&);
59 #endif
61 template<class T>
62 struct extract_wrap_base
64 # if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
65 BOOST_STATIC_CONSTANT(bool,
66 value = sizeof(check_overload(get_pointer(*(T*)0)))
67 == sizeof(yes_overload)
70 static wrap_base const* extract(T const* ptr)
72 return extract_impl(ptr, boost::mpl::bool_<value>());
75 static wrap_base const* extract_impl(T const* ptr, boost::mpl::true_)
77 return dynamic_cast<wrap_base const*>(
78 get_pointer(*ptr));
81 static wrap_base const* extract_impl(T const* ptr, boost::mpl::false_)
83 return dynamic_cast<wrap_base const*>(ptr);
86 static wrap_base* extract(T* ptr)
88 return extract_impl(ptr, boost::mpl::bool_<value>());
91 static wrap_base* extract_impl(T* ptr, boost::mpl::true_)
93 return dynamic_cast<wrap_base*>(
94 get_pointer(*ptr));
97 static wrap_base* extract_impl(T* ptr, boost::mpl::false_)
99 return dynamic_cast<wrap_base*>(ptr);
101 # else
102 static wrap_base const* extract(T const* ptr)
104 return dynamic_cast<wrap_base const*>(get_pointer(*ptr));
107 static wrap_base* extract(T* ptr)
109 return dynamic_cast<wrap_base*>(get_pointer(*ptr));
111 # endif
114 struct default_back_reference {};
116 template<class T>
117 struct back_reference_impl : default_back_reference
119 static bool extract(lua_State* L, T const* ptr)
121 if (!has_wrapper) return false;
123 if (wrap_base const* p = extract_wrap_base<T>::extract(ptr))
125 wrap_access::ref(*p).get(L);
126 return true;
129 return false;
132 static bool move(lua_State* L, T* ptr)
134 if (!has_wrapper) return false;
136 if (wrap_base* p = extract_wrap_base<T>::extract(ptr))
138 assert(wrap_access::ref(*p).m_strong_ref.is_valid());
139 wrap_access::ref(*p).get(L);
140 wrap_access::ref(*p).m_strong_ref.reset();
141 return true;
144 return false;
147 static bool has_wrapper;
150 template<class T>
151 bool back_reference_impl<T>::has_wrapper = false;
153 template<class T>
154 struct back_reference_do_nothing
156 static bool extract(lua_State*, T const*)
158 return false;
161 static bool move(lua_State*, T*)
163 return false;
167 } // namespace detail
169 #ifndef LUABIND_NO_RTTI
171 template<class T>
172 struct back_reference
173 : boost::mpl::if_<
174 boost::is_polymorphic<T>
175 , detail::back_reference_impl<T>
176 , detail::back_reference_do_nothing<T>
177 >::type
181 #else
183 template<class T>
184 struct back_reference
185 : detail::back_reference_do_nothing<T>
189 #endif
191 } // namespace luabind
193 #endif // BACK_REFERENCE_040510_HPP