*** empty log message ***
[luabind.git] / luabind / class.hpp
blob69415338aa19460a67231c5280e2aa83d5074de2
1 // Copyright (c) 2003 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.
24 #ifndef LUABIND_CLASS_HPP_INCLUDED
25 #define LUABIND_CLASS_HPP_INCLUDED
28 Issues:
29 -------
30 * done *
31 move all exceptions to the exception.hpp header
33 * done *
34 Since functions can be overridden, the constness of the member functions
35 must be taken into account.
37 * solved for member functions, not application operator *
38 if we have a base class that defines a function a derived class must be able to
39 override that function (not just overload). Right now we just add the other overload
40 to the overloads list and will probably get an ambiguity. If we want to support this
41 each method_rep must include a vector of type_info pointers for each parameter.
42 Operators do not have this problem, since operators always have to have
43 it's own type as one of the arguments, no ambiguity can occur. Application
44 operator, on the other hand, would have this problem.
45 Properties cannot be overloaded, so they should always be overridden.
46 If this is to work for application operator, we really need to specify if an application
47 operator is const or not.
49 If one class registers two functions with the same name and the same
50 signature, there's currently no error. The last registered function will
51 be the one that's used.
52 How do we know which class registered the function? If the function was
53 defined by the base class, it is a legal operation, to override it.
54 we cannot look at the pointer offset, since it always will be zero for one of the bases.
56 * done *
57 We do not currently run unwrap_other<> on the parameters given to the application
58 operators when we register them.
60 * done *
61 if the first matched binary operator does not match the parameters we have to manually
62 check if the right parameter has a matching operator.
64 * I think this is resolved *
65 There is currently a restriction that operators must take their parameters as const references
66 or as copies. This could be solved by specifying special wrapper types for const references and
67 non-const references. Binary operators shouldn't implicitly convert it's parameters to const&.
69 * done *
70 The application operator do not currently work on const objects. Again, to solve this we need
71 some kind of wrapper to say that the self object is const.
73 Make sure we don't have any memory leaks when we use lua_error()
75 We should avoid names that begins with lua_ (in our own scopes) since the lua distribution
76 have plenty of defines with that prefix.
78 Optimize by calling lua_rawset/get instead of lua_settable/gettable
80 * done *
81 use ordinary function pointers instead of boost::function.
82 the boost::function is only used on member functions now, We have to use it in order
83 to support free functions as member functions.
85 * solved *
86 when we register classes we should import all methods and properties
87 from the base classes into the class. We will then need to offset the object pointer
88 on a per method/property basis. This will allow methods from the base class to be
89 overloaded without shadowing the base class. The method lookup will also be
90 more efficient.
92 remove methods from methodtable of classrep when overloading them in lua
94 * done *
95 we currently set uninitialized references to -1, they should be set to LUA_NOREF!
97 * done *
98 the error exception class should avoid heap allocations
100 Todo:
101 -----
103 document custom policies, custom converters
105 store the instance object for policies.
107 support the __concat metamethod. This is a bit tricky, since it cannot be
108 treated as a normal operator. It is a binary operator but we want to use the
109 __tostring implementation for both arguments.
111 smart pointer support
113 scopes
115 __finalize function on lua classes
117 make all proxy_callers one policy based class
119 make all proxy_objects one policy based class
121 static functions
125 #include <luabind/config.hpp>
127 #include <string>
128 #include <map>
129 #include <vector>
130 #include <cassert>
132 #include <boost/static_assert.hpp>
133 #include <boost/type_traits.hpp>
134 #include <boost/bind.hpp>
135 #include <boost/function.hpp>
136 #include <boost/preprocessor/repetition/enum_params.hpp>
137 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
138 #include <boost/preprocessor/repetition/repeat.hpp>
139 #include <boost/type_traits/is_same.hpp>
140 #include <boost/mpl/list.hpp>
141 #include <boost/mpl/apply.hpp>
142 #include <boost/mpl/lambda.hpp>
143 #include <boost/mpl/logical.hpp>
144 #include <boost/mpl/find_if.hpp>
145 #include <boost/mpl/apply_if.hpp>
146 #include <boost/mpl/logical.hpp>
148 #include <luabind/config.hpp>
149 #include <luabind/scope.hpp>
150 #include <luabind/detail/constructor.hpp>
151 #include <luabind/detail/call.hpp>
152 #include <luabind/detail/signature_match.hpp>
153 #include <luabind/detail/primitives.hpp>
154 #include <luabind/detail/property.hpp>
155 #include <luabind/detail/typetraits.hpp>
156 #include <luabind/detail/class_rep.hpp>
157 #include <luabind/detail/method_rep.hpp>
158 #include <luabind/detail/construct_rep.hpp>
159 #include <luabind/detail/object_rep.hpp>
160 #include <luabind/detail/operators.hpp>
161 #include <luabind/detail/calc_arity.hpp>
162 #include <luabind/detail/call_member.hpp>
163 #include <luabind/detail/enum_maker.hpp>
164 #include <luabind/detail/get_signature.hpp>
165 #include <luabind/detail/implicit_cast.hpp>
166 #include <luabind/detail/operator_id.hpp>
168 namespace luabind
170 namespace detail
172 struct unspecified {};
175 template<class T, class X1 = detail::unspecified, class X2 = detail::unspecified, class X3 = detail::unspecified>
176 struct class_;
178 namespace detail
180 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, class A)>
181 double is_bases_helper(const bases<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, A)>&);
183 #ifndef BOOST_MSVC
184 template<class T>
185 char is_bases_helper(const T&);
186 #else
187 char is_bases_helper(...);
188 #endif
190 template<class T>
191 struct is_bases
193 static const T& t;
195 BOOST_STATIC_CONSTANT(bool, value = sizeof(is_bases_helper(t)) == sizeof(double));
196 typedef boost::mpl::bool_<value> type;
197 BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_bases,(T))
200 double is_not_unspecified_helper(const unspecified*);
201 char is_not_unspecified_helper(...);
203 template<class T>
204 struct is_not_unspecified
206 BOOST_STATIC_CONSTANT(bool, value = sizeof(is_not_unspecified_helper(static_cast<T*>(0))) == sizeof(char));
207 typedef boost::mpl::bool_<value> type;
208 BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_not_unspecified,(T))
211 template<class Predicate>
212 struct get_predicate
214 typedef typename boost::mpl::and_<
215 Predicate
216 , is_not_unspecified<boost::mpl::_1>
217 > type;
220 template<class Parameters, class Predicate, class DefaultValue>
221 struct extract_parameter
223 typedef typename get_predicate<Predicate>::type pred;
224 typedef typename boost::mpl::find_if<Parameters, pred>::type iterator;
225 typedef typename boost::mpl::apply_if<boost::is_same<iterator, typename boost::mpl::end<Parameters>::type>
226 , boost::mpl::identity<DefaultValue>
227 , iterator
228 >::type type;
231 int function_dispatcher(lua_State* L);
233 // this should know about the smart pointer type.
234 // and should really do:
235 // get_pointer(*static_cast<SmartPointer*>(obj_ptr))
236 // to extract the held pointer.
237 template<class HeldType, class T, class F, class Policies>
238 struct function_callback_non_null
240 function_callback_non_null(F f_): f(f_) {}
241 inline int operator()(lua_State* L, void* obj_ptr)
243 HeldType& held_obj = *static_cast<HeldType*>(obj_ptr);
245 T* ptr = get_pointer(held_obj);
246 // BOOST_STATIC_ASSERT((boost::is_same<HeldType, detail::null_type>::value == false));
248 // std::cout << "HeldType: " << typeid(HeldType).name() << "\n";
250 return call(f, ptr, L, static_cast<Policies*>(this));
252 F f;
255 template<class T, class F, class Policies>
256 struct function_callback_null_type : Policies
258 function_callback_null_type(F f_): f(f_) {}
259 inline int operator()(lua_State* L, void* obj_ptr)
261 // std::cout << "HeldType: null_type\n";
262 T* ptr = static_cast<T*>(obj_ptr);
263 return call(f, ptr, L, static_cast<Policies*>(this));
265 F f;
268 template<class HeldType, class T, class F, class Policies>
269 struct function_callback_s
271 typedef typename
272 boost::mpl::if_<boost::is_same<HeldType,detail::null_type>
273 , function_callback_null_type<T,F,Policies>
274 , function_callback_non_null<HeldType,T,F,Policies>
275 >::type type;
278 template<class T, class F, class Policies>
279 struct match_function_callback_s
281 static inline int apply(lua_State* L)
283 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
284 F fptr = 0;
285 return match(fptr, L, obj->flags() & object_rep::constant, static_cast<Policies*>(0));
289 // prints the types of the values on the stack, in the
290 // range [start_index, lua_gettop()]
291 inline std::string stack_content_by_name(lua_State* L, int start_index)
293 std::string ret;
294 int top = lua_gettop(L);
295 for (int i = start_index; i <= top; ++i)
297 object_rep* obj = is_class_object(L, i);
298 class_rep* crep = is_class_rep(L, i)?(class_rep*)lua_touserdata(L, i):0;
299 if (obj == 0 && crep == 0)
301 int type = lua_type(L, i);
302 ret += lua_typename(L, type);
304 else if (obj)
306 if (obj->flags() & object_rep::constant) ret += "const ";
307 ret += obj->crep()->name();
309 else if (crep)
311 ret += "<";
312 ret += crep->name();
313 ret += ">";
315 if (i < top) ret += ", ";
317 return ret;
320 struct create_class
322 static int stage2(lua_State* L)
325 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
326 assert((crep != 0) && "internal error, please report");
327 assert((is_class_rep(L, lua_upvalueindex(1))) && "internal error, please report");
329 #ifndef LUABIND_NO_ERROR_CHECKING
331 if (!is_class_rep(L, 1))
333 lua_pushstring(L, "expected class to derive from or a newline");
334 lua_error(L);
337 #endif
339 class_rep* base = static_cast<class_rep*>(lua_touserdata(L, 1));
341 class_rep::base_info binfo;
343 binfo.pointer_offset = 0;
344 binfo.base = base;
345 crep->add_base_class(binfo);
347 if (base->get_class_type() == class_rep::lua_class)
349 // copy base class members
351 detail::getref(L, crep->table_ref());
352 detail::getref(L, base->table_ref());
353 lua_pushnil(L);
355 while (lua_next(L, -2))
357 lua_pushstring(L, "__init");
358 if (lua_equal(L, -1, -3))
360 lua_pop(L, 2);
361 continue;
364 lua_pushstring(L, "__finalize");
365 if (lua_equal(L, -1, -3))
367 lua_pop(L, 2);
368 continue;
371 lua_pushvalue(L, -2); // copy key
372 lua_insert(L, -2);
373 lua_settable(L, -5);
377 crep->set_type(base->type());
379 return 0;
382 static int stage1(lua_State* L)
385 #ifndef LUABIND_NO_ERROR_CHECKING
387 if (lua_gettop(L) != 1 || lua_type(L, 1) != LUA_TSTRING || lua_isnumber(L, 1))
389 lua_pushstring(L, "invalid construct, expected class name");
390 lua_error(L);
393 #endif
395 const char* name = lua_tostring(L, 1);
397 void* c = lua_newuserdata(L, sizeof(class_rep));
398 new(c) class_rep(L, name);
400 // make the class globally available
401 lua_pushstring(L, name);
402 lua_pushvalue(L, -2);
403 lua_settable(L, LUA_GLOBALSINDEX);
405 // also add it to the closure as return value
406 lua_pushcclosure(L, &stage2, 1);
408 return 1;
412 template<class Type>
413 struct register_wrapped_type
415 template<class Signature, class Policies>
416 static void apply(detail::construct_rep::overload_t& o, const Signature*, const Policies*)
418 o.set_wrapped_constructor(
419 &detail::construct_wrapped_class<Type, Policies, Signature>::apply
424 template<>
425 struct register_wrapped_type<detail::null_type>
427 template<class Signature, class Policies>
428 static void apply(detail::construct_rep::overload_t&, const Signature*, const Policies*) {}
432 // if the class is held by a smart pointer, we need to be able to
433 // implicitly dereference the pointer when needed.
435 template<class UnderlyingT, class HeldT>
436 struct extract_underlying_type
438 static void* extract(void* ptr)
440 HeldT& held_obj = *reinterpret_cast<HeldT*>(ptr);
441 UnderlyingT* underlying_ptr = get_pointer(held_obj);
442 return underlying_ptr;
447 template<class HeldType>
448 struct internal_held_type_extractor
450 typedef void*(*extractor_fun)(void*);
452 template<class T>
453 static extractor_fun apply(detail::type<T>)
455 return detail::extract_underlying_type<T, HeldType>::extract;
459 template<>
460 struct internal_held_type_extractor<detail::null_type>
462 typedef void*(*extractor_fun)(void*);
464 template<class T>
465 static extractor_fun apply(detail::type<T>)
467 return 0;
471 template<class HeldType>
472 struct internal_held_type
474 static LUABIND_TYPE_INFO apply()
476 return LUABIND_TYPEID(HeldType);
480 template<>
481 struct internal_held_type<detail::null_type>
483 static LUABIND_TYPE_INFO apply()
485 return LUABIND_INVALID_TYPE_INFO;
489 } // detail
504 struct class_base: detail::scoped_object
506 protected:
508 struct base_desc
510 LUABIND_TYPE_INFO type;
511 int ptr_offset;
514 private:
516 #ifndef NDEBUG
517 bool m_cloned;
518 #endif
520 const char* m_name;
522 std::map<const char*, detail::method_rep, detail::ltstr> m_methods;
524 // datamembers, some members may be readonly, and
525 // only have a getter function
526 std::map<const char*, detail::class_rep::callback, detail::ltstr> m_getters;
527 std::map<const char*, detail::class_rep::callback, detail::ltstr> m_setters;
529 // the operators in lua
530 std::vector<detail::class_rep::operator_callback> m_operators[detail::number_of_operators];
531 std::map<const char*, int, detail::ltstr> m_static_constants;
533 std::vector<base_desc> m_bases;
534 detail::construct_rep m_constructor;
536 void(*m_destructor)(void*);
537 void*(*m_extractor)(void*);
539 LUABIND_TYPE_INFO m_type;
540 LUABIND_TYPE_INFO m_held_type;
542 #ifndef LUABIND_DONT_COPY_STRINGS
543 // the maps that contains char pointers points into
544 // this vector of strings.
545 std::vector<char*> m_strings;
546 #endif
548 protected:
550 void set_type(LUABIND_TYPE_INFO t) { m_type = t; }
551 void set_held_type(LUABIND_TYPE_INFO t) { m_held_type = t; }
552 void set_extractor(void*(*f)(void*)) { m_extractor = f; }
553 void set_destructor(void(*f)(void*)) { m_destructor = f; }
555 inline void add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
557 detail::class_rep::callback c;
558 c.func = g;
559 c.pointer_offset = 0;
560 #ifndef LUABIND_DONT_COPY_STRINGS
561 m_strings.push_back(detail::dup_string(name));
562 m_getters[m_strings.back()] = c;
563 #else
564 m_getters[name] = c;
565 #endif
568 inline void add_setter(const char* name, const boost::function2<int, lua_State*, int>& s)
570 detail::class_rep::callback c;
571 c.func = s;
572 c.pointer_offset = 0;
573 #ifndef LUABIND_DONT_COPY_STRINGS
574 m_strings.push_back(detail::dup_string(name));
575 m_setters[m_strings.back()] = c;
576 #else
577 m_setters[name] = c;
578 #endif
581 void add_base(const base_desc& b)
583 m_bases.push_back(b);
586 public:
588 void add_constructor(const detail::construct_rep::overload_t& o)
590 m_constructor.overloads.push_back(o);
593 void add_method(const char* name, const detail::overload_rep& o)
595 #ifdef LUABIND_DONT_COPY_STRINGS
596 detail::method_rep& method = m_methods[name];
597 method.name = name;
598 #else
599 m_strings.push_back(detail::dup_string(name));
600 detail::method_rep& method = m_methods[m_strings.back()];
601 method.name = m_strings.back();
602 #endif
603 method.add_overload(o);
604 method.crep = 0;
607 #ifndef LUABIND_NO_ERROR_CHECKING
608 inline void add_operator(int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), void(*sig)(lua_State*, std::string&), int arity)
609 #else
610 inline void add_operator(int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
611 #endif
613 detail::class_rep::operator_callback o;
614 o.set_fun(func);
615 o.set_match_fun(matcher);
616 o.set_arity(arity);
618 #ifndef LUABIND_NO_ERROR_CHECKING
620 o.set_sig_fun(sig);
622 #endif
623 m_operators[op_id].push_back(o);
632 const char* name() const { return m_name; }
634 class_base(const char* name): m_name(name)
636 #ifndef NDEBUG
637 m_cloned = false;
638 #endif
641 virtual ~class_base()
643 // if we are copying strings, we have to destroy them too
644 #ifndef LUABIND_DONT_COPY_STRINGS
645 for (std::vector<char*>::iterator i = m_strings.begin(); i != m_strings.end(); ++i)
646 delete[] *i;
647 #endif
650 // pushes the class_rep on the lua stack
651 virtual void commit(lua_State* L)
653 detail::class_rep* crep;
655 detail::class_registry* r = detail::class_registry::get_registry(L);
656 // create a class_rep structure for this class.
657 // allocate it within lua to let lua collect it on
658 // lua_close(). This is better than allocating it
659 // as a static, since it will then be destructed
660 // when the program exits instead.
661 // warning: we assume that lua will not
662 // move the userdata memory.
663 lua_newuserdata(L, sizeof(detail::class_rep));
664 crep = reinterpret_cast<detail::class_rep*>(lua_touserdata(L, -1));
666 new(crep) detail::class_rep(m_type, m_name, L, m_destructor, m_held_type, m_extractor);
668 // register this new type in the class registry
669 r->add_class(m_type, crep);
671 // add methods
672 for (std::map<const char*, detail::method_rep, detail::ltstr>::iterator i = m_methods.begin();
673 i != m_methods.end();
674 ++i)
676 i->second.crep = crep;
678 std::swap(crep->m_methods, m_methods);
680 // constructors
681 m_constructor.swap(crep->m_constructor);
683 #ifndef LUABIND_DONT_COPY_STRINGS
684 std::swap(crep->m_strings, m_strings);
685 #endif
687 std::swap(crep->m_getters, m_getters);
688 std::swap(crep->m_setters, m_setters);
690 for(int i = 0; i < detail::number_of_operators; ++i)
691 std::swap(crep->m_operators[i], m_operators[i]);
693 std::swap(crep->m_static_constants, m_static_constants);
695 for (std::vector<base_desc>::iterator i = m_bases.begin();
696 i != m_bases.end();
697 ++i)
699 detail::class_registry* r = detail::class_registry::get_registry(L);
701 // the baseclass' class_rep structure
702 detail::class_rep* bcrep = r->find_class(i->type);
704 detail::class_rep::base_info base;
705 base.pointer_offset = i->ptr_offset;
706 base.base = bcrep;
708 crep->add_base_class(base);
712 // destructive copy
713 virtual luabind::detail::scoped_object* clone()
715 assert(m_cloned == false);
717 #ifndef NDEBUG
718 m_cloned = true;
719 #endif
721 class_base* ret = new class_base(m_name);
723 std::swap(ret->m_getters, m_getters);
724 std::swap(ret->m_setters, m_setters);
726 for(int i = 0; i < detail::number_of_operators; ++i)
727 std::swap(ret->m_operators[i], m_operators[i]);
729 std::swap(ret->m_static_constants, m_static_constants);
730 ret->m_destructor = m_destructor;
732 std::swap(ret->m_bases, m_bases);
733 std::swap(ret->m_methods, m_methods);
734 m_constructor.swap(ret->m_constructor);
736 #ifndef LUABIND_DONT_COPY_STRINGS
737 std::swap(ret->m_strings, m_strings);
738 #endif
740 return ret;
755 // registers a class in the lua environment
756 template<class T, class X1, class X2, class X3>
757 struct class_: class_base
759 typedef class_<T, X1, X2, X3> self_t;
761 private:
763 lua_State* m_L;
765 template<class A, class B, class C, class D>
766 class_(const class_<A,B,C,D>&);
768 public:
770 // WrappedType MUST inherit from T
771 typedef typename detail::extract_parameter<
772 boost::mpl::vector3<X1,X2,X3>
773 , boost::is_base_and_derived<T, boost::mpl::_>
774 /* , boost::mpl::not_<
775 boost::mpl::or_<
776 detail::is_bases<boost::mpl::_>
777 , boost::is_base_and_derived<boost::mpl::_, T>
780 , detail::null_type
781 >::type WrappedType;
783 typedef typename detail::extract_parameter<
784 boost::mpl::vector3<X1,X2,X3>
785 , boost::mpl::not_<
786 boost::mpl::or_<
787 boost::mpl::or_<
788 detail::is_bases<boost::mpl::_>
789 , boost::is_base_and_derived<boost::mpl::_, T>
791 , boost::is_base_and_derived<T, boost::mpl::_>
794 , detail::null_type
795 >::type HeldType;
797 // this function generates conversion information
798 // in the given class_rep structure. It will be able
799 // to implicitly cast to the given template type
800 template<class To>
801 void gen_base_info(detail::type<To>)
803 // fist, make sure the given base class is registered.
804 // if it's not registered we can't push it's lua table onto
805 // the stack because it doesn't have a table
807 // try to cast this type to the base type and remember
808 // the pointer offset. For multiple inheritance the pointer
809 // may change when casting. Since we need to be able to
810 // cast we need this pointer offset.
811 // store the information in this class' base class-vector
812 base_desc base;
813 base.type = LUABIND_TYPEID(To);
814 base.ptr_offset = detail::ptr_offset(detail::type<T>(), detail::type<To>());
815 add_base(base);
818 void gen_base_info(detail::type<detail::null_type>)
821 #define LUABIND_GEN_BASE_INFO(z, n, text) gen_base_info(detail::type<B##n>());
823 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, class B)>
824 void generate_baseclass_list(detail::type<bases<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, B)> >)
826 BOOST_PP_REPEAT(LUABIND_MAX_BASES, LUABIND_GEN_BASE_INFO, _)
829 #undef LUABIND_GEN_BASE_INFO
831 // this is the internal version of def() it is run from both overloads
832 // of def. It has two versions, one where a contstructor is registered
833 // and one where a function is registered
834 template<class Policies>
835 struct internal_def_s
837 template<class F>
838 static void apply(const char* name, F f, class_base* c)
840 // std::cout << "HeldType2: " << typeid(HeldType).name() << "\n";
842 detail::overload_rep o(f, static_cast<Policies*>(0));
844 typedef LUABIND_MSVC_TYPENAME detail::function_callback_s<HeldType,T,F,Policies>::type call_t;
846 o.set_match_fun(&detail::match_function_callback_s<T,F,Policies>::apply);
847 o.call_fun = boost::bind<int>(call_t(f), _1, _2);
849 #ifndef LUABIND_NO_ERROR_CHECKING
851 o.set_sig_fun(&detail::get_member_signature<F>::apply);
853 #endif
855 c->add_method(name, o);
858 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)>
859 static void apply(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>, class_base* c)
861 // std::cout << "HeldType2: " << typeid(HeldType).name() << "\n";
863 detail::construct_rep::overload_t o;
865 o.set_constructor(
866 &detail::construct_class<
868 ,Policies
869 ,constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>
870 >::apply
873 // if we have a WrappedType, we have to register it's constructor
874 // but if it's null_type (no WrappedType) we should not register it
875 detail::register_wrapped_type<WrappedType>::apply(o,
876 static_cast<const constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>*>(0),
877 static_cast<const Policies*>(0));
880 o.set_match_fun(
881 &detail::constructor_match<
882 constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>
884 ,Policies
885 >::apply);
887 #ifndef LUABIND_NO_ERROR_CHECKING
889 o.set_sig_fun(&detail::get_signature<constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> >::apply);
891 #endif
893 typedef constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> con_t;
895 o.set_arity(detail::calc_arity<con_t::arity>::apply(con_t(), static_cast<Policies*>(0)));
897 c->add_constructor(o);
902 class_(lua_State* L_, const char* name): class_base(name), m_L(L_) { init(); }
903 class_(const char* name): class_base(name), m_L(0) { init(); }
905 // TODO: we sould probably commit the object someplace else
906 ~class_()
908 if (m_L)
910 lua_pushstring(m_L, name());
911 commit(m_L);
912 lua_settable(m_L, LUA_GLOBALSINDEX);
916 template<class F>
917 class_& def(const char* name, F f)
919 internal_def_s<detail::null_type>::apply(name, f, this);
920 return *this;
923 template<class F, class Policies>
924 class_& def(const char* name, F f, const Policies&)
926 internal_def_s<Policies>::apply(name, f, this);
927 return *this;
930 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)>
931 class_& def(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> sig)
933 internal_def_s<detail::null_type>::apply(sig, this);
934 return *this;
937 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A), class Policies>
938 class_& def(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> sig, const Policies& policies)
940 internal_def_s<Policies>::apply(sig, this);
941 return *this;
944 template<class Getter>
945 class_& property(const char* name, Getter g)
947 add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, detail::null_type>(), _1, _2, g));
948 return *this;
951 template<class Getter, class MaybeSetter>
952 class_& property(const char* name, Getter g, MaybeSetter s)
954 return property_impl(name, g, s, boost::mpl::bool_<detail::is_policy_cons<MaybeSetter>::value>());
957 template<class Getter, class Setter, class GetPolicies>
958 class_& property(const char* name, Getter g, Setter s, const GetPolicies& get_policies)
960 add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, GetPolicies>(get_policies), _1, _2, g));
961 add_setter(name, boost::bind<int>(detail::set_caller<T, Setter, detail::null_type>(), _1, _2, s));
962 return *this;
965 template<class Getter, class Setter, class GetPolicies, class SetPolicies>
966 class_& property(const char* name
967 , Getter g, Setter s
968 , const GetPolicies& get_policies
969 , const SetPolicies& set_policies)
971 add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, GetPolicies>(get_policies), _1, _2, g));
972 add_setter(name, boost::bind<int>(detail::set_caller<T, Setter, GetPolicies>(set_policies), _1, _2, s));
973 return *this;
976 template<class D>
977 class_& def_readonly(const char* name, D T::*member_ptr)
979 add_getter(name, boost::bind<int>(detail::auto_get<T,D,detail::null_type>(), _1, _2, member_ptr));
980 return *this;
983 template<class D, class Policies>
984 class_& def_readonly(const char* name, D T::*member_ptr, const Policies& policies)
986 add_getter(name, boost::bind<int>(detail::auto_get<T,D,Policies>(policies), _1, _2, member_ptr));
987 return *this;
990 template<class D>
991 class_& def_readwrite(const char* name, D T::*member_ptr)
993 add_getter(name, boost::bind<int>(detail::auto_get<T,D,detail::null_type>(), _1, _2, member_ptr));
994 add_setter(name, boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr));
995 return *this;
998 template<class D, class GetPolicies>
999 class_& def_readwrite(const char* name, D T::*member_ptr, const GetPolicies& get_policies)
1001 add_getter(name, boost::bind<int>(detail::auto_get<T,D,GetPolicies>(get_policies), _1, _2, member_ptr));
1002 add_setter(name, boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr));
1003 return *this;
1006 template<class D, class GetPolicies, class SetPolicies>
1007 class_& def_readwrite(const char* name, D T::*member_ptr, const GetPolicies& get_policies, const SetPolicies& set_policies)
1009 add_getter(name, boost::bind<int>(detail::auto_get<T,D,GetPolicies>(get_policies), _1, _2, member_ptr));
1010 add_setter(name, boost::bind<int>(detail::auto_set<T,D,SetPolicies>(set_policies), _1, _2, member_ptr));
1011 return *this;
1014 template<class op_id, class Left, class Right, class Policies>
1015 class_& def(detail::operator_<op_id, Left, Right>, const Policies& policies)
1017 typedef typename detail::operator_unwrapper<Policies, op_id, T, Left, Right> op_type;
1018 #ifndef LUABIND_NO_ERROR_CHECKING
1019 add_operator(op_type::get_id()
1020 , &op_type::execute
1021 , &op_type::match
1022 , &detail::get_signature<constructor<typename op_type::left_t, typename op_type::right_t> >::apply
1023 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1024 #else
1025 add_operator(op_type::get_id()
1026 , &op_type::execute
1027 , &op_type::match
1028 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1029 #endif
1030 return *this;
1033 template<class op_id, class Left, class Right>
1034 class_& def(detail::operator_<op_id, Left, Right>)
1036 typedef typename detail::operator_unwrapper<detail::null_type, op_id, T, Left, Right> op_type;
1038 #ifndef LUABIND_NO_ERROR_CHECKING
1039 add_operator(op_type::get_id()
1040 , &op_type::execute
1041 , &op_type::match
1042 , &detail::get_signature<constructor<LUABIND_MSVC_TYPENAME op_type::left_t, LUABIND_MSVC_TYPENAME op_type::right_t> >::apply
1043 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1044 #else
1045 add_operator(op_type::get_id()
1046 , &op_type::execute
1047 , &op_type::match
1048 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1049 #endif
1050 return *this;
1053 template<class Signature, bool Constant>
1054 class_& def(detail::application_operator<Signature, Constant>*)
1056 typedef detail::application_operator<Signature, Constant, detail::null_type> op_t;
1058 int arity = detail::calc_arity<Signature::arity>::apply(Signature(), static_cast<detail::null_type*>(0));
1060 #ifndef LUABIND_NO_ERROR_CHECKING
1061 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, &detail::get_signature<Signature>::apply, arity + 1);
1062 #else
1063 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, arity + 1);
1064 #endif
1066 return *this;
1069 template<class Signature, bool Constant, class Policies>
1070 class_& def(detail::application_operator<Signature, Constant>*, const Policies& policies)
1072 typedef detail::application_operator<Signature, Constant, Policies> op_t;
1074 int arity = detail::calc_arity<Signature::arity>::apply(Signature(), static_cast<Policies*>(0));
1076 #ifndef LUABIND_NO_ERROR_CHECKING
1077 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, &detail::get_signature<Signature>::apply, arity + 1);
1078 #else
1079 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, arity + 1);
1080 #endif
1082 return *this;
1085 detail::enum_maker<self_t> enum_(const char*)
1087 return detail::enum_maker<self_t>(*this);
1090 private:
1092 void init()
1094 typedef typename detail::extract_parameter<
1095 boost::mpl::vector3<X1,X2,X3>
1096 , boost::mpl::or_<
1097 detail::is_bases<boost::mpl::_>
1098 , boost::is_base_and_derived<boost::mpl::_, T>
1100 , no_bases
1101 >::type bases_t;
1103 typedef typename
1104 boost::mpl::if_<detail::is_bases<bases_t>
1105 , bases_t
1106 , bases<bases_t>
1107 >::type Base;
1109 set_type(LUABIND_TYPEID(T));
1110 set_held_type(detail::internal_held_type<HeldType>::apply());
1111 set_extractor(detail::internal_held_type_extractor<HeldType>::apply(detail::type<T>()));
1112 set_destructor(detail::destructor_s<T>::apply);
1114 generate_baseclass_list(detail::type<Base>());
1117 template<class Getter, class GetPolicies>
1118 class_& property_impl(const char* name,
1119 Getter g,
1120 GetPolicies policies,
1121 boost::mpl::bool_<true>)
1123 add_getter(name, boost::bind<int>(detail::get_caller<T,Getter,GetPolicies>(policies), _1, _2, g));
1124 return *this;
1127 template<class Getter, class Setter>
1128 class_& property_impl(const char* name,
1129 Getter g,
1130 Setter s,
1131 boost::mpl::bool_<false>)
1133 add_getter(name, boost::bind<int>(detail::get_caller<T,Getter,detail::null_type>(), _1, _2, g));
1134 add_setter(name, boost::bind<int>(detail::set_caller<T,Setter,detail::null_type>(), _1, _2, s));
1135 return *this;
1141 #endif // LUABIND_CLASS_HPP_INCLUDED