revised scope documentation and added smart pointer documentation.
[luabind.git] / luabind / class.hpp
blob891a34b634ea631f78485822c8851a794e663267
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 ------------------------------------------------------
31 * solved for member functions, not application operator *
32 if we have a base class that defines a function a derived class must be able to
33 override that function (not just overload). Right now we just add the other overload
34 to the overloads list and will probably get an ambiguity. If we want to support this
35 each method_rep must include a vector of type_info pointers for each parameter.
36 Operators do not have this problem, since operators always have to have
37 it's own type as one of the arguments, no ambiguity can occur. Application
38 operator, on the other hand, would have this problem.
39 Properties cannot be overloaded, so they should always be overridden.
40 If this is to work for application operator, we really need to specify if an application
41 operator is const or not.
43 If one class registers two functions with the same name and the same
44 signature, there's currently no error. The last registered function will
45 be the one that's used.
46 How do we know which class registered the function? If the function was
47 defined by the base class, it is a legal operation, to override it.
48 we cannot look at the pointer offset, since it always will be zero for one of the bases.
52 TODO:
53 ------------------------------------------------------
55 add access to the keys on iterators
57 finish scopes (and document)
59 finish smart pointer support
60 * we need a special case in the value_converter matcher to know that smart
61 pointers can be implicitly cast to base types.
62 * holder_type<const A> must be supported by the converters
63 * the adopt policy should not be able to adopt pointers to held_types. This
64 must be prohibited.
65 * name_of_type must recognize holder_types and not return "custom"
66 * maybe it's better to avoid LUABIND_TYPEID() etc. in user code. get_const_holder
67 * document it
69 document the new yield-policy
71 chache operators and finalizers in the class_rep. For lua classes
72 we currently do a lookup each time we need to know if a lua class
73 has a finalizer or an operator.
75 instead of registering the name of free functions and make a lookup in
76 the register to see if we are overloading, look in the actual namespace
77 where we are registering the function to see if there already is a function
78 with the same name there, and in that case, add an overload to it.
80 static functions, this could be implemented by letting classes contain
81 other declarations (classes or functions)
83 document custom policies, custom converters
85 store the instance object for policies.
87 support the __concat metamethod. This is a bit tricky, since it cannot be
88 treated as a normal operator. It is a binary operator but we want to use the
89 __tostring implementation for both arguments.
93 #include <luabind/config.hpp>
95 #include <string>
96 #include <map>
97 #include <vector>
98 #include <cassert>
100 #include <boost/static_assert.hpp>
101 #include <boost/type_traits.hpp>
102 #include <boost/bind.hpp>
103 #include <boost/function.hpp>
104 #include <boost/preprocessor/repetition/enum_params.hpp>
105 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
106 #include <boost/preprocessor/repetition/repeat.hpp>
107 #include <boost/type_traits/is_same.hpp>
108 #include <boost/mpl/list.hpp>
109 #include <boost/mpl/apply.hpp>
110 #include <boost/mpl/lambda.hpp>
111 #include <boost/mpl/logical.hpp>
112 #include <boost/mpl/find_if.hpp>
113 #include <boost/mpl/apply_if.hpp>
114 #include <boost/mpl/logical.hpp>
116 #include <luabind/config.hpp>
117 #include <luabind/scope.hpp>
118 #include <luabind/detail/constructor.hpp>
119 #include <luabind/detail/call.hpp>
120 #include <luabind/detail/signature_match.hpp>
121 #include <luabind/detail/primitives.hpp>
122 #include <luabind/detail/property.hpp>
123 #include <luabind/detail/typetraits.hpp>
124 #include <luabind/detail/class_rep.hpp>
125 #include <luabind/detail/method_rep.hpp>
126 #include <luabind/detail/construct_rep.hpp>
127 #include <luabind/detail/object_rep.hpp>
128 #include <luabind/detail/operators.hpp>
129 #include <luabind/detail/calc_arity.hpp>
130 #include <luabind/detail/call_member.hpp>
131 #include <luabind/detail/enum_maker.hpp>
132 #include <luabind/detail/get_signature.hpp>
133 #include <luabind/detail/implicit_cast.hpp>
134 #include <luabind/detail/operator_id.hpp>
136 namespace luabind
138 namespace detail
140 struct unspecified {};
143 template<class T, class X1 = detail::unspecified, class X2 = detail::unspecified, class X3 = detail::unspecified>
144 struct class_;
146 inline LUABIND_TYPE_INFO get_const_holder(...)
148 return LUABIND_INVALID_TYPE_INFO;
151 namespace detail
153 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, class A)>
154 double is_bases_helper(const bases<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, A)>&);
156 #ifndef BOOST_MSVC
157 template<class T>
158 char is_bases_helper(const T&);
159 #else
160 char is_bases_helper(...);
161 #endif
163 template<class T>
164 struct is_bases
166 static const T& t;
168 BOOST_STATIC_CONSTANT(bool, value = sizeof(is_bases_helper(t)) == sizeof(double));
169 typedef boost::mpl::bool_<value> type;
170 BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_bases,(T))
173 double is_not_unspecified_helper(const unspecified*);
174 char is_not_unspecified_helper(...);
176 template<class T>
177 struct is_not_unspecified
179 BOOST_STATIC_CONSTANT(bool, value = sizeof(is_not_unspecified_helper(static_cast<T*>(0))) == sizeof(char));
180 typedef boost::mpl::bool_<value> type;
181 BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_not_unspecified,(T))
184 template<class Predicate>
185 struct get_predicate
187 typedef typename boost::mpl::and_<
188 Predicate
189 , is_not_unspecified<boost::mpl::_1>
190 > type;
193 template<class Parameters, class Predicate, class DefaultValue>
194 struct extract_parameter
196 typedef typename get_predicate<Predicate>::type pred;
197 typedef typename boost::mpl::find_if<Parameters, pred>::type iterator;
198 typedef typename boost::mpl::apply_if<boost::is_same<iterator, typename boost::mpl::end<Parameters>::type>
199 , boost::mpl::identity<DefaultValue>
200 , iterator
201 >::type type;
204 int function_dispatcher(lua_State* L);
206 // this should know about the smart pointer type.
207 // and should really do:
208 // get_pointer(*static_cast<SmartPointer*>(obj_ptr))
209 // to extract the held pointer.
210 template<class HeldType, class T, class F, class Policies>
211 struct function_callback_non_null : Policies
213 function_callback_non_null(F f_): f(f_) {}
214 inline int operator()(lua_State* L, void* obj_ptr)
216 HeldType& held_obj = *static_cast<HeldType*>(obj_ptr);
218 T* ptr = static_cast<T*>(get_pointer(held_obj));
220 return call(f, ptr, L, static_cast<Policies*>(this));
222 F f;
225 template<class T, class F, class Policies>
226 struct function_callback_null_type : Policies
228 function_callback_null_type(F f_): f(f_) {}
229 inline int operator()(lua_State* L, void* obj_ptr)
231 // std::cout << "HeldType: null_type\n";
232 T* ptr = static_cast<T*>(obj_ptr);
233 return call(f, ptr, L, static_cast<Policies*>(this));
235 F f;
238 template<class HeldType, class T, class F, class Policies>
239 struct function_callback_s
241 typedef typename
242 boost::mpl::if_<boost::is_same<HeldType,detail::null_type>
243 , function_callback_null_type<T,F,Policies>
244 , function_callback_non_null<HeldType,T,F,Policies>
245 >::type type;
248 template<class T, class F, class Policies>
249 struct match_function_callback_s
251 static inline int apply(lua_State* L)
253 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
254 F fptr = 0;
255 return match(fptr, L, obj->flags() & object_rep::constant, static_cast<Policies*>(0));
259 // prints the types of the values on the stack, in the
260 // range [start_index, lua_gettop()]
262 std::string stack_content_by_name(lua_State* L, int start_index);
264 struct create_class
266 static int stage1(lua_State* L);
267 static int stage2(lua_State* L);
270 template<class Type>
271 struct register_wrapped_type
273 template<class Signature, class Policies>
274 static void apply(detail::construct_rep::overload_t& o, const Signature*, const Policies*)
276 o.set_wrapped_constructor(
277 &detail::construct_wrapped_class<Type, Policies, Signature>::apply
282 template<>
283 struct register_wrapped_type<detail::null_type>
285 template<class Signature, class Policies>
286 static void apply(detail::construct_rep::overload_t&, const Signature*, const Policies*) {}
290 // if the class is held by a smart pointer, we need to be able to
291 // implicitly dereference the pointer when needed.
293 template<class UnderlyingT, class HeldT>
294 struct extract_underlying_type
296 static void* extract(void* ptr)
298 HeldT& held_obj = *reinterpret_cast<HeldT*>(ptr);
299 UnderlyingT* underlying_ptr = static_cast<UnderlyingT*>(get_pointer(held_obj));
300 return underlying_ptr;
305 template<class HeldType>
306 struct internal_held_type_extractor
308 typedef void*(*extractor_fun)(void*);
310 template<class T>
311 static extractor_fun apply(detail::type<T>)
313 return detail::extract_underlying_type<T, HeldType>::extract;
317 template<>
318 struct internal_held_type_extractor<detail::null_type>
320 typedef void*(*extractor_fun)(void*);
322 template<class T>
323 static extractor_fun apply(detail::type<T>)
325 return 0;
330 // this is simply a selector that returns the type_info
331 // of the held type, or invalid_type_info if we don't have
332 // a held_type
333 template<class HeldType>
334 struct internal_held_type
336 static LUABIND_TYPE_INFO apply()
338 return LUABIND_TYPEID(HeldType);
342 template<>
343 struct internal_held_type<detail::null_type>
345 static LUABIND_TYPE_INFO apply()
347 return LUABIND_INVALID_TYPE_INFO;
352 // this is the actual held_type constructor
353 template<class HeldType, class T>
354 struct internal_construct_held_type
356 static void apply(void* target, void* raw_pointer)
358 new(target) HeldType(static_cast<T*>(raw_pointer));
362 // the followinf two functions are the ones that returns
363 // a pointer to a held_type_constructor, or 0 if there
364 // is no held_type
365 template<class HeldType>
366 struct internal_held_type_constructor
368 typedef void(*constructor)(void*,void*);
369 template<class T>
370 static constructor apply(detail::type<T>)
372 return &internal_construct_held_type<HeldType, T>::apply;
376 template<>
377 struct internal_held_type_constructor<detail::null_type>
379 typedef void(*constructor)(void*,void*);
380 template<class T>
381 static constructor apply(detail::type<T>)
383 return 0;
388 // this is a selector that returns the size of the held_type
389 // or 0 if we don't have a held_type
390 template <class HeldType>
391 struct internal_held_type_size
393 static int apply() { return sizeof(HeldType); }
396 template <>
397 struct internal_held_type_size<detail::null_type>
399 static int apply() { return 0; }
403 // if we have a held type, return the destructor to it
404 // note the difference. The held_type should only be destructed (not deleted)
405 // since it's constructed in the lua userdata
406 template<class HeldType>
407 struct internal_held_type_destructor
409 typedef void(*destructor_t)(void*);
410 template<class T>
411 static destructor_t apply(detail::type<T>)
413 return &detail::destruct_only_s<HeldType>::apply;
417 // if we don't have a held type, return the destructor of the raw type
418 template<>
419 struct internal_held_type_destructor<detail::null_type>
421 typedef void(*destructor_t)(void*);
422 template<class T>
423 static destructor_t apply(detail::type<T>)
425 return &detail::delete_s<T>::apply;
429 template<class T>
430 struct get_holder_alignment
432 static int apply()
434 return boost::alignment_of<T>::value;
438 template<>
439 struct get_holder_alignment<detail::null_type>
441 static int apply()
443 return 0;
448 } // detail
463 struct class_base: detail::scoped_object
465 protected:
467 struct base_desc
469 LUABIND_TYPE_INFO type;
470 int ptr_offset;
473 private:
475 #ifndef NDEBUG
476 bool m_cloned;
477 #endif
479 const char* m_name;
481 std::map<const char*, detail::method_rep, detail::ltstr> m_methods;
483 // datamembers, some members may be readonly, and
484 // only have a getter function
485 std::map<const char*, detail::class_rep::callback, detail::ltstr> m_getters;
486 std::map<const char*, detail::class_rep::callback, detail::ltstr> m_setters;
488 // the operators in lua
489 std::vector<detail::class_rep::operator_callback> m_operators[detail::number_of_operators];
490 std::map<const char*, int, detail::ltstr> m_static_constants;
492 std::vector<base_desc> m_bases;
493 detail::construct_rep m_constructor;
495 void(*m_destructor)(void*);
496 void*(*m_extractor)(void*);
497 void(*m_construct_held_type)(void*, void*);
498 int m_held_type_size;
499 int m_held_type_alignment;
501 LUABIND_TYPE_INFO m_type;
502 LUABIND_TYPE_INFO m_held_type;
503 LUABIND_TYPE_INFO m_const_holder_type;
505 #ifndef LUABIND_DONT_COPY_STRINGS
506 // the maps that contains char pointers points into
507 // this vector of strings.
508 std::vector<char*> m_strings;
509 #endif
511 public:
513 // public 'cause of enum_maker, FIX
514 void add_static_constant(const char* name, int val)
516 m_static_constants[name] = val;
519 protected:
521 void set_type(LUABIND_TYPE_INFO t) { m_type = t; }
522 void set_held_type(LUABIND_TYPE_INFO t) { m_held_type = t; }
524 void set_const_holder_type(LUABIND_TYPE_INFO t)
526 m_const_holder_type = t;
529 void set_extractor(void*(*f)(void*)) { m_extractor = f; }
530 void set_held_type_constructor(void(*f)(void*,void*)) { m_construct_held_type = f; }
531 void set_destructor(void(*f)(void*)) { m_destructor = f; }
532 void set_held_type_size(int s) { m_held_type_size = s; }
533 void set_held_type_alignment(int n) { m_held_type_alignment = n; }
535 inline void add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
537 detail::class_rep::callback c;
538 c.func = g;
539 c.pointer_offset = 0;
540 #ifndef LUABIND_DONT_COPY_STRINGS
541 m_strings.push_back(detail::dup_string(name));
542 m_getters[m_strings.back()] = c;
543 #else
544 m_getters[name] = c;
545 #endif
548 inline void add_setter(const char* name, const boost::function2<int, lua_State*, int>& s)
550 detail::class_rep::callback c;
551 c.func = s;
552 c.pointer_offset = 0;
553 #ifndef LUABIND_DONT_COPY_STRINGS
554 m_strings.push_back(detail::dup_string(name));
555 m_setters[m_strings.back()] = c;
556 #else
557 m_setters[name] = c;
558 #endif
561 void add_base(const base_desc& b)
563 m_bases.push_back(b);
566 public:
568 void add_constructor(const detail::construct_rep::overload_t& o)
570 m_constructor.overloads.push_back(o);
573 void add_method(const char* name, const detail::overload_rep& o)
575 #ifdef LUABIND_DONT_COPY_STRINGS
576 detail::method_rep& method = m_methods[name];
577 method.name = name;
578 #else
579 m_strings.push_back(detail::dup_string(name));
580 detail::method_rep& method = m_methods[m_strings.back()];
581 method.name = m_strings.back();
582 #endif
583 method.add_overload(o);
584 method.crep = 0;
587 #ifndef LUABIND_NO_ERROR_CHECKING
588 inline void add_operator(int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), void(*sig)(lua_State*, std::string&), int arity)
589 #else
590 inline void add_operator(int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
591 #endif
593 detail::class_rep::operator_callback o;
594 o.set_fun(func);
595 o.set_match_fun(matcher);
596 o.set_arity(arity);
598 #ifndef LUABIND_NO_ERROR_CHECKING
600 o.set_sig_fun(sig);
602 #endif
603 m_operators[op_id].push_back(o);
612 const char* name() const { return m_name; }
614 class_base(const char* name)
616 #ifndef LUABIND_DONT_COPY_STRINGS
617 m_strings.push_back(detail::dup_string(name));
618 m_name = m_strings.back();
619 #else
620 m_name = name;
621 #endif
623 #ifndef NDEBUG
624 m_cloned = false;
625 #endif
628 virtual ~class_base()
630 // if we are copying strings, we have to destroy them too
631 #ifndef LUABIND_DONT_COPY_STRINGS
632 for (std::vector<char*>::iterator i = m_strings.begin(); i != m_strings.end(); ++i)
633 delete[] *i;
634 #endif
637 // pushes the class_rep on the lua stack
638 virtual void commit(lua_State* L)
640 assert(!m_cloned && "class already commited");
642 scope::init(L);
644 detail::getref(L, scope_stack::top(L));
645 lua_pushstring(L, m_name);
647 detail::class_rep* crep;
649 detail::class_registry* r = detail::class_registry::get_registry(L);
650 // create a class_rep structure for this class.
651 // allocate it within lua to let lua collect it on
652 // lua_close(). This is better than allocating it
653 // as a static, since it will then be destructed
654 // when the program exits instead.
655 // warning: we assume that lua will not
656 // move the userdata memory.
657 lua_newuserdata(L, sizeof(detail::class_rep));
658 crep = reinterpret_cast<detail::class_rep*>(lua_touserdata(L, -1));
660 new(crep) detail::class_rep(m_type, m_name, L, m_destructor, m_held_type, m_const_holder_type, m_extractor, m_construct_held_type, m_held_type_size, m_held_type_alignment);
662 // register this new type in the class registry
663 r->add_class(m_type, crep);
664 if (!(LUABIND_TYPE_INFO_EQUAL(m_held_type, LUABIND_INVALID_TYPE_INFO)))
666 // if we have a held type
667 // we have to register it in the class-table
668 // but only for the base class, if it already
669 // exists, we don't have to register it
670 detail::class_rep* c = r->find_class(m_held_type);
671 if (c == 0) r->add_class(m_held_type, crep);
674 // add methods
675 for (std::map<const char*, detail::method_rep, detail::ltstr>::iterator i = m_methods.begin();
676 i != m_methods.end();
677 ++i)
679 i->second.crep = crep;
681 std::swap(crep->m_methods, m_methods);
683 // constructors
684 m_constructor.swap(crep->m_constructor);
686 #ifndef LUABIND_DONT_COPY_STRINGS
687 assert(crep->m_strings.empty() && "Internal error");
688 std::swap(crep->m_strings, m_strings);
689 #endif
691 std::swap(crep->m_getters, m_getters);
692 std::swap(crep->m_setters, m_setters);
694 for(int i = 0; i < detail::number_of_operators; ++i)
695 std::swap(crep->m_operators[i], m_operators[i]);
697 std::swap(crep->m_static_constants, m_static_constants);
699 for (std::vector<base_desc>::iterator i = m_bases.begin();
700 i != m_bases.end();
701 ++i)
703 detail::class_registry* r = detail::class_registry::get_registry(L);
705 // the baseclass' class_rep structure
706 detail::class_rep* bcrep = r->find_class(i->type);
708 detail::class_rep::base_info base;
709 base.pointer_offset = i->ptr_offset;
710 base.base = bcrep;
712 crep->add_base_class(base);
715 lua_settable(L, -3);
716 lua_pop(L, 1);
720 // destructive copy
721 virtual luabind::detail::scoped_object* clone()
723 assert(m_cloned == false);
725 #ifndef NDEBUG
726 m_cloned = true;
727 #endif
729 class_base* ret = new class_base(m_name);
731 std::swap(ret->m_getters, m_getters);
732 std::swap(ret->m_setters, m_setters);
734 for(int i = 0; i < detail::number_of_operators; ++i)
735 std::swap(ret->m_operators[i], m_operators[i]);
737 std::swap(ret->m_static_constants, m_static_constants);
738 ret->m_destructor = m_destructor;
739 ret->m_extractor = m_extractor;
740 ret->m_construct_held_type = m_construct_held_type;
741 ret->m_held_type_size = m_held_type_size;
743 std::swap(ret->m_bases, m_bases);
744 std::swap(ret->m_methods, m_methods);
745 m_constructor.swap(ret->m_constructor);
747 ret->m_type = m_type;
748 ret->m_held_type = m_held_type;
749 ret->m_const_holder_type = m_const_holder_type;
751 #ifndef LUABIND_DONT_COPY_STRINGS
752 std::swap(ret->m_strings, m_strings);
753 #endif
755 return ret;
770 // registers a class in the lua environment
771 template<class T, class X1, class X2, class X3>
772 struct class_: class_base
774 typedef class_<T, X1, X2, X3> self_t;
776 lua_State* m_L;
778 private:
780 template<class A, class B, class C, class D>
781 class_(const class_<A,B,C,D>&);
783 public:
785 // WrappedType MUST inherit from T
786 typedef typename detail::extract_parameter<
787 boost::mpl::vector3<X1,X2,X3>
788 , boost::is_base_and_derived<T, boost::mpl::_>
789 /* , boost::mpl::not_<
790 boost::mpl::or_<
791 detail::is_bases<boost::mpl::_>
792 , boost::is_base_and_derived<boost::mpl::_, T>
795 , detail::null_type
796 >::type WrappedType;
798 typedef typename detail::extract_parameter<
799 boost::mpl::vector3<X1,X2,X3>
800 , boost::mpl::not_<
801 boost::mpl::or_<
802 boost::mpl::or_<
803 detail::is_bases<boost::mpl::_>
804 , boost::is_base_and_derived<boost::mpl::_, T>
806 , boost::is_base_and_derived<T, boost::mpl::_>
809 , detail::null_type
810 >::type HeldType;
812 // this function generates conversion information
813 // in the given class_rep structure. It will be able
814 // to implicitly cast to the given template type
815 template<class To>
816 void gen_base_info(detail::type<To>)
818 // fist, make sure the given base class is registered.
819 // if it's not registered we can't push it's lua table onto
820 // the stack because it doesn't have a table
822 // try to cast this type to the base type and remember
823 // the pointer offset. For multiple inheritance the pointer
824 // may change when casting. Since we need to be able to
825 // cast we need this pointer offset.
826 // store the information in this class' base class-vector
827 base_desc base;
828 base.type = LUABIND_TYPEID(To);
829 base.ptr_offset = detail::ptr_offset(detail::type<T>(), detail::type<To>());
830 add_base(base);
833 void gen_base_info(detail::type<detail::null_type>)
836 #define LUABIND_GEN_BASE_INFO(z, n, text) gen_base_info(detail::type<B##n>());
838 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, class B)>
839 void generate_baseclass_list(detail::type<bases<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, B)> >)
841 BOOST_PP_REPEAT(LUABIND_MAX_BASES, LUABIND_GEN_BASE_INFO, _)
844 #undef LUABIND_GEN_BASE_INFO
846 // this is the internal version of def() it is run from both overloads
847 // of def. It has two versions, one where a contstructor is registered
848 // and one where a function is registered
849 template<class Policies>
850 struct internal_def_s
852 template<class F>
853 static void apply(const char* name, F f, class_base* c)
855 // std::cout << "HeldType2: " << typeid(HeldType).name() << "\n";
857 detail::overload_rep o(f, static_cast<Policies*>(0));
859 typedef LUABIND_MSVC_TYPENAME detail::function_callback_s<HeldType,T,F,Policies>::type call_t;
861 o.set_match_fun(&detail::match_function_callback_s<T,F,Policies>::apply);
862 o.call_fun = boost::bind<int>(call_t(f), _1, _2);
864 #ifndef LUABIND_NO_ERROR_CHECKING
866 o.set_sig_fun(&detail::get_member_signature<F>::apply);
868 #endif
870 c->add_method(name, o);
873 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)>
874 static void apply(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>, class_base* c)
876 // std::cout << "HeldType2: " << typeid(HeldType).name() << "\n";
878 detail::construct_rep::overload_t o;
880 o.set_constructor(
881 &detail::construct_class<
883 ,Policies
884 ,constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>
885 >::apply
888 // if we have a WrappedType, we have to register it's constructor
889 // but if it's null_type (no WrappedType) we should not register it
890 detail::register_wrapped_type<WrappedType>::apply(o,
891 static_cast<const constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>*>(0),
892 static_cast<const Policies*>(0));
895 o.set_match_fun(
896 &detail::constructor_match<
897 constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>
899 ,Policies
900 >::apply);
902 #ifndef LUABIND_NO_ERROR_CHECKING
904 o.set_sig_fun(&detail::get_signature<constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> >::apply);
906 #endif
908 typedef constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> con_t;
910 o.set_arity(detail::calc_arity<con_t::arity>::apply(con_t(), static_cast<Policies*>(0)));
912 c->add_constructor(o);
916 class_(lua_State* L, const char* name): class_base(name), m_L(L) { init(); }
917 class_(const char* name): class_base(name), m_L(0) { init(); }
919 ~class_()
921 if (m_L != 0)
923 commit(m_L);
927 template<class F>
928 class_& def(const char* name, F f)
930 internal_def_s<detail::null_type>::apply(name, f, this);
931 return *this;
934 template<class F, class Policies>
935 class_& def(const char* name, F f, const Policies&)
937 internal_def_s<Policies>::apply(name, f, this);
938 return *this;
941 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)>
942 class_& def(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> sig)
944 internal_def_s<detail::null_type>::apply(sig, this);
945 return *this;
948 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A), class Policies>
949 class_& def(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> sig, const Policies& policies)
951 internal_def_s<Policies>::apply(sig, this);
952 return *this;
955 template<class Getter>
956 class_& property(const char* name, Getter g)
958 add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, detail::null_type>(), _1, _2, g));
959 return *this;
962 template<class Getter, class MaybeSetter>
963 class_& property(const char* name, Getter g, MaybeSetter s)
965 return property_impl(name, g, s, boost::mpl::bool_<detail::is_policy_cons<MaybeSetter>::value>());
968 template<class Getter, class Setter, class GetPolicies>
969 class_& property(const char* name, Getter g, Setter s, const GetPolicies& get_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, detail::null_type>(), _1, _2, s));
973 return *this;
976 template<class Getter, class Setter, class GetPolicies, class SetPolicies>
977 class_& property(const char* name
978 , Getter g, Setter s
979 , const GetPolicies& get_policies
980 , const SetPolicies& set_policies)
982 add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, GetPolicies>(get_policies), _1, _2, g));
983 add_setter(name, boost::bind<int>(detail::set_caller<T, Setter, GetPolicies>(set_policies), _1, _2, s));
984 return *this;
987 template<class D>
988 class_& def_readonly(const char* name, D T::*member_ptr)
990 add_getter(name, boost::bind<int>(detail::auto_get<T,D,detail::null_type>(), _1, _2, member_ptr));
991 return *this;
994 template<class D, class Policies>
995 class_& def_readonly(const char* name, D T::*member_ptr, const Policies& policies)
997 add_getter(name, boost::bind<int>(detail::auto_get<T,D,Policies>(policies), _1, _2, member_ptr));
998 return *this;
1001 template<class D>
1002 class_& def_readwrite(const char* name, D T::*member_ptr)
1004 add_getter(name, boost::bind<int>(detail::auto_get<T,D,detail::null_type>(), _1, _2, member_ptr));
1005 add_setter(name, boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr));
1006 return *this;
1009 template<class D, class GetPolicies>
1010 class_& def_readwrite(const char* name, D T::*member_ptr, const GetPolicies& get_policies)
1012 add_getter(name, boost::bind<int>(detail::auto_get<T,D,GetPolicies>(get_policies), _1, _2, member_ptr));
1013 add_setter(name, boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr));
1014 return *this;
1017 template<class D, class GetPolicies, class SetPolicies>
1018 class_& def_readwrite(const char* name, D T::*member_ptr, const GetPolicies& get_policies, const SetPolicies& set_policies)
1020 add_getter(name, boost::bind<int>(detail::auto_get<T,D,GetPolicies>(get_policies), _1, _2, member_ptr));
1021 add_setter(name, boost::bind<int>(detail::auto_set<T,D,SetPolicies>(set_policies), _1, _2, member_ptr));
1022 return *this;
1025 template<class op_id, class Left, class Right, class Policies>
1026 class_& def(detail::operator_<op_id, Left, Right>, const Policies& policies)
1028 typedef typename detail::operator_unwrapper<Policies, op_id, T, Left, Right> op_type;
1029 #ifndef LUABIND_NO_ERROR_CHECKING
1030 add_operator(op_type::get_id()
1031 , &op_type::execute
1032 , &op_type::match
1033 , &detail::get_signature<constructor<typename op_type::left_t, typename op_type::right_t> >::apply
1034 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1035 #else
1036 add_operator(op_type::get_id()
1037 , &op_type::execute
1038 , &op_type::match
1039 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1040 #endif
1041 return *this;
1044 template<class op_id, class Left, class Right>
1045 class_& def(detail::operator_<op_id, Left, Right>)
1047 typedef typename detail::operator_unwrapper<detail::null_type, op_id, T, Left, Right> op_type;
1049 #ifndef LUABIND_NO_ERROR_CHECKING
1050 add_operator(op_type::get_id()
1051 , &op_type::execute
1052 , &op_type::match
1053 , &detail::get_signature<constructor<LUABIND_MSVC_TYPENAME op_type::left_t, LUABIND_MSVC_TYPENAME op_type::right_t> >::apply
1054 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1055 #else
1056 add_operator(op_type::get_id()
1057 , &op_type::execute
1058 , &op_type::match
1059 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1060 #endif
1061 return *this;
1064 template<class Signature, bool Constant>
1065 class_& def(detail::application_operator<Signature, Constant>*)
1067 typedef detail::application_operator<Signature, Constant, detail::null_type> op_t;
1069 int arity = detail::calc_arity<Signature::arity>::apply(Signature(), static_cast<detail::null_type*>(0));
1071 #ifndef LUABIND_NO_ERROR_CHECKING
1072 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, &detail::get_signature<Signature>::apply, arity + 1);
1073 #else
1074 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, arity + 1);
1075 #endif
1077 return *this;
1080 template<class Signature, bool Constant, class Policies>
1081 class_& def(detail::application_operator<Signature, Constant>*, const Policies& policies)
1083 typedef detail::application_operator<Signature, Constant, Policies> op_t;
1085 int arity = detail::calc_arity<Signature::arity>::apply(Signature(), static_cast<Policies*>(0));
1087 #ifndef LUABIND_NO_ERROR_CHECKING
1088 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, &detail::get_signature<Signature>::apply, arity + 1);
1089 #else
1090 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, arity + 1);
1091 #endif
1093 return *this;
1096 detail::enum_maker<self_t> enum_(const char*)
1098 return detail::enum_maker<self_t>(*this);
1101 private:
1103 void init()
1105 typedef typename detail::extract_parameter<
1106 boost::mpl::vector3<X1,X2,X3>
1107 , boost::mpl::or_<
1108 detail::is_bases<boost::mpl::_>
1109 , boost::is_base_and_derived<boost::mpl::_, T>
1111 , no_bases
1112 >::type bases_t;
1114 typedef typename
1115 boost::mpl::if_<detail::is_bases<bases_t>
1116 , bases_t
1117 , bases<bases_t>
1118 >::type Base;
1120 set_type(LUABIND_TYPEID(T));
1121 set_held_type(detail::internal_held_type<HeldType>::apply());
1122 set_const_holder_type(get_const_holder(detail::type<HeldType>()));
1123 set_extractor(detail::internal_held_type_extractor<HeldType>::apply(detail::type<T>()));
1124 set_held_type_constructor(detail::internal_held_type_constructor<HeldType>::apply(detail::type<T>()));
1125 set_held_type_size(detail::internal_held_type_size<HeldType>::apply());
1126 set_destructor(detail::internal_held_type_destructor<HeldType>::apply(detail::type<T>()));
1128 set_held_type_alignment(detail::get_holder_alignment<HeldType>::apply());
1130 generate_baseclass_list(detail::type<Base>());
1133 template<class Getter, class GetPolicies>
1134 class_& property_impl(const char* name,
1135 Getter g,
1136 GetPolicies policies,
1137 boost::mpl::bool_<true>)
1139 add_getter(name, boost::bind<int>(detail::get_caller<T,Getter,GetPolicies>(policies), _1, _2, g));
1140 return *this;
1143 template<class Getter, class Setter>
1144 class_& property_impl(const char* name,
1145 Getter g,
1146 Setter s,
1147 boost::mpl::bool_<false>)
1149 add_getter(name, boost::bind<int>(detail::get_caller<T,Getter,detail::null_type>(), _1, _2, g));
1150 add_setter(name, boost::bind<int>(detail::set_caller<T,Setter,detail::null_type>(), _1, _2, s));
1151 return *this;
1157 #endif // LUABIND_CLASS_HPP_INCLUDED