1 // Copyright Daniel Wallin 2008. 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)
4 
5 #if !BOOST_PP_IS_ITERATING
6 
7 # ifndef LUABIND_DETAIL_CONSTRUCTOR_081018_HPP
8 #  define LUABIND_DETAIL_CONSTRUCTOR_081018_HPP
9 
10 #  include <luabind/detail/inheritance.hpp>
11 #  include <luabind/get_main_thread.hpp>
12 #  include <luabind/detail/object.hpp>
13 #  include <luabind/wrapper_base.hpp>
14 
15 #  include <boost/preprocessor/iteration/iterate.hpp>
16 #  include <boost/preprocessor/iteration/local.hpp>
17 #  include <boost/preprocessor/repetition/enum_binary_params.hpp>
18 #  include <boost/preprocessor/repetition/enum_params.hpp>
19 
20 namespace luabind { namespace detail {
21 
inject_backref(lua_State *,void *,void *)22 inline void inject_backref(lua_State*, void*, void*)
23 {}
24 
25 template <class T>
inject_backref(lua_State * L,T * p,wrap_base *)26 void inject_backref(lua_State* L, T* p, wrap_base*)
27 {
28     weak_ref(get_main_thread(L), L, 1).swap(wrap_access::ref(*p));
29 }
30 
31 template <std::size_t Arity, class T, class Pointer, class Signature>
32 struct construct_aux;
33 
34 template <class T, class Pointer, class Signature>
35 struct construct
36   : construct_aux<mpl::size<Signature>::value - 2, T, Pointer, Signature>
37 {};
38 
39 template <class T, class Pointer, class Signature>
40 struct construct_aux<0, T, Pointer, Signature>
41 {
42     typedef pointer_holder<Pointer, T> holder_type;
43 
operator ()luabind::detail::construct_aux44     void operator()(argument const& self_) const
45     {
46         object_rep* self = touserdata<object_rep>(self_);
47 #ifdef LUABIND_USE_CXX11
48         std::unique_ptr<T> instance(new T);
49 #else
50         std::auto_ptr<T> instance(new T);
51 #endif
52         inject_backref(self_.interpreter(), instance.get(), instance.get());
53 
54         void* naked_ptr = instance.get();
55         Pointer ptr(instance.release());
56 
57         void* storage = self->allocate(sizeof(holder_type));
58 
59         self->set_instance(new (storage) holder_type(
60 #ifdef LUABIND_USE_CXX11
61             std::move(ptr), registered_class<T>::id, naked_ptr));
62 #else
63             ptr, registered_class<T>::id, naked_ptr));
64 #endif
65     }
66 };
67 
68 #  define BOOST_PP_ITERATION_PARAMS_1 \
69     (3, (1, LUABIND_MAX_ARITY, <luabind/detail/constructor.hpp>))
70 #  include BOOST_PP_ITERATE()
71 
72 }} // namespace luabind::detail
73 
74 # endif // LUABIND_DETAIL_CONSTRUCTOR_081018_HPP
75 
76 #else // !BOOST_PP_IS_ITERATING
77 
78 # define N BOOST_PP_ITERATION()
79 
80 template <class T, class Pointer, class Signature>
81 struct construct_aux<N, T, Pointer, Signature>
82 {
83     typedef typename mpl::begin<Signature>::type first;
84     typedef typename mpl::next<first>::type iter0;
85 
86 # define BOOST_PP_LOCAL_MACRO(n) \
87     typedef typename mpl::next< \
88         BOOST_PP_CAT(iter,BOOST_PP_DEC(n))>::type BOOST_PP_CAT(iter,n); \
89     typedef typename BOOST_PP_CAT(iter,n)::type BOOST_PP_CAT(a,BOOST_PP_DEC(n));
90 
91 # define BOOST_PP_LOCAL_LIMITS (1,N)
92 # include BOOST_PP_LOCAL_ITERATE()
93 
94     typedef pointer_holder<Pointer, T> holder_type;
95 
operator ()construct_aux96     void operator()(argument const& self_, BOOST_PP_ENUM_BINARY_PARAMS(N,a,_)) const
97     {
98         object_rep* self = touserdata<object_rep>(self_);
99 #ifdef LUABIND_USE_CXX11
100         std::unique_ptr<T> instance(new T(BOOST_PP_ENUM_PARAMS(N,_)));
101 #else
102         std::auto_ptr<T> instance(new T(BOOST_PP_ENUM_PARAMS(N,_)));
103 #endif
104         inject_backref(self_.interpreter(), instance.get(), instance.get());
105 
106         void* naked_ptr = instance.get();
107         Pointer ptr(instance.release());
108 
109         void* storage = self->allocate(sizeof(holder_type));
110 
111         self->set_instance(new (storage) holder_type(
112 #ifdef LUABIND_USE_CXX11
113             std::move(ptr), registered_class<T>::id, naked_ptr));
114 #else
115             ptr, registered_class<T>::id, naked_ptr));
116 #endif
117     }
118 };
119 
120 # undef N
121 
122 #endif
123