added set_error_callback() and set_cast_failed_callback() and improved the exceptions...
[luabind.git] / luabind / class.hpp
blob7f68aa9f77616db4bf4085b5174deec24e37b3cd
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 make all proxy_callers one policy based class
117 make all proxy_objects one policy based class
119 static functions
123 #include <luabind/config.hpp>
125 #include <string>
126 #include <map>
127 #include <vector>
128 #include <cassert>
130 #include <boost/static_assert.hpp>
131 #include <boost/type_traits.hpp>
132 #include <boost/bind.hpp>
133 #include <boost/function.hpp>
134 #include <boost/preprocessor/repetition/enum_params.hpp>
135 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
136 #include <boost/preprocessor/repetition/repeat.hpp>
137 #include <boost/type_traits/is_same.hpp>
138 #include <boost/mpl/list.hpp>
139 #include <boost/mpl/apply.hpp>
140 #include <boost/mpl/lambda.hpp>
141 #include <boost/mpl/logical.hpp>
142 #include <boost/mpl/find_if.hpp>
143 #include <boost/mpl/apply_if.hpp>
144 #include <boost/mpl/logical.hpp>
146 #include <luabind/config.hpp>
147 #include <luabind/detail/constructor.hpp>
148 #include <luabind/detail/call.hpp>
149 #include <luabind/detail/signature_match.hpp>
150 #include <luabind/detail/primitives.hpp>
151 #include <luabind/detail/property.hpp>
152 #include <luabind/detail/typetraits.hpp>
153 #include <luabind/detail/class_rep.hpp>
154 #include <luabind/detail/method_rep.hpp>
155 #include <luabind/detail/construct_rep.hpp>
156 #include <luabind/detail/object_rep.hpp>
157 #include <luabind/detail/operators.hpp>
158 #include <luabind/detail/call_member.hpp>
159 #include <luabind/detail/enum_maker.hpp>
160 #include <luabind/detail/get_signature.hpp>
161 #include <luabind/detail/implicit_cast.hpp>
162 #include <luabind/detail/calc_arity.hpp>
164 namespace luabind
166 namespace detail
168 struct unspecified {};
171 template<class T, class X1 = detail::unspecified, class X2 = detail::unspecified, class X3 = detail::unspecified>
172 struct class_;
174 namespace detail
176 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, class A)>
177 double is_bases_helper(const bases<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, A)>&);
179 #ifndef BOOST_MSVC
180 template<class T>
181 char is_bases_helper(const T&);
182 #else
183 char is_bases_helper(...);
184 #endif
186 template<class T>
187 struct is_bases
189 static const T& t;
191 BOOST_STATIC_CONSTANT(bool, value = sizeof(is_bases_helper(t)) == sizeof(double));
192 typedef boost::mpl::bool_<value> type;
193 BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_bases,(T))
196 double is_not_unspecified_helper(const unspecified*);
197 char is_not_unspecified_helper(...);
199 template<class T>
200 struct is_not_unspecified
202 BOOST_STATIC_CONSTANT(bool, value = sizeof(is_not_unspecified_helper(static_cast<T*>(0))) == sizeof(char));
203 typedef boost::mpl::bool_<value> type;
204 BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_not_unspecified,(T))
207 template<class Predicate>
208 struct get_predicate
210 typedef typename boost::mpl::and_<
211 Predicate
212 , is_not_unspecified<boost::mpl::_1>
213 > type;
216 template<class Parameters, class Predicate, class DefaultValue>
217 struct extract_parameter
219 typedef typename get_predicate<Predicate>::type pred;
220 typedef typename boost::mpl::find_if<Parameters, pred>::type iterator;
221 typedef typename boost::mpl::apply_if<boost::is_same<iterator, typename boost::mpl::end<Parameters>::type>
222 , boost::mpl::identity<DefaultValue>
223 , iterator
224 >::type type;
227 int function_dispatcher(lua_State* L);
229 // this should know about the smart pointer type.
230 // and should really do:
231 // get_pointer(*static_cast<SmartPointer*>(obj_ptr))
232 // to extract the held pointer.
233 template<class HeldType, class T, class F, class Policies>
234 struct function_callback_non_null
236 function_callback_non_null(F f_): f(f_) {}
237 inline int operator()(lua_State* L, void* obj_ptr)
239 HeldType& held_obj = *static_cast<HeldType*>(obj_ptr);
241 T* ptr = get_pointer(held_obj);
242 // BOOST_STATIC_ASSERT((boost::is_same<HeldType, detail::null_type>::value == false));
244 // std::cout << "HeldType: " << typeid(HeldType).name() << "\n";
246 return call(f, ptr, L, static_cast<Policies*>(this));
248 F f;
251 template<class T, class F, class Policies>
252 struct function_callback_null_type : Policies
254 function_callback_null_type(F f_): f(f_) {}
255 inline int operator()(lua_State* L, void* obj_ptr)
257 // std::cout << "HeldType: null_type\n";
258 T* ptr = static_cast<T*>(obj_ptr);
259 return call(f, ptr, L, static_cast<Policies*>(this));
261 F f;
264 template<class HeldType, class T, class F, class Policies>
265 struct function_callback_s
267 typedef typename
268 boost::mpl::if_<boost::is_same<HeldType,detail::null_type>
269 , function_callback_null_type<T,F,Policies>
270 , function_callback_non_null<HeldType,T,F,Policies>
271 >::type type;
274 template<class T, class F, class Policies>
275 struct match_function_callback_s
277 static inline int apply(lua_State* L)
279 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
280 F fptr = 0;
281 return match(fptr, L, obj->flags() & object_rep::constant, static_cast<Policies*>(0));
285 // prints the types of the values on the stack, in the
286 // range [start_index, lua_gettop()]
287 inline std::string stack_content_by_name(lua_State* L, int start_index)
289 std::string ret;
290 int top = lua_gettop(L);
291 for (int i = start_index; i <= top; ++i)
293 object_rep* obj = is_class_object(L, i);
294 class_rep* crep = is_class_rep(L, i)?(class_rep*)lua_touserdata(L, i):0;
295 if (obj == 0 && crep == 0)
297 int type = lua_type(L, i);
298 ret += lua_typename(L, type);
300 else if (obj)
302 if (obj->flags() & object_rep::constant) ret += "const ";
303 ret += obj->crep()->name();
305 else if (crep)
307 ret += "<";
308 ret += crep->name();
309 ret += ">";
311 if (i < top) ret += ", ";
313 return ret;
316 struct create_class
318 static int stage2(lua_State* L)
321 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
322 assert((crep != 0) && "internal error, please report");
323 assert((is_class_rep(L, lua_upvalueindex(1))) && "internal error, please report");
325 #ifndef LUABIND_NO_ERROR_CHECKING
327 if (!is_class_rep(L, 1))
329 lua_pushstring(L, "expected class to derive from or a newline");
330 lua_error(L);
333 #endif
335 class_rep* base = static_cast<class_rep*>(lua_touserdata(L, 1));
337 class_rep::base_info binfo;
339 binfo.pointer_offset = 0;
340 binfo.base = base;
341 crep->add_base(binfo);
343 if (base->get_class_type() == class_rep::lua_class)
345 // copy base class members
347 detail::getref(L, crep->table_ref());
348 detail::getref(L, base->table_ref());
349 lua_pushnil(L);
351 while (lua_next(L, -2))
353 lua_pushvalue(L, -2); // copy key
354 lua_insert(L, -2);
355 lua_settable(L, -5);
359 crep->set_type(base->type());
361 return 0;
364 static int stage1(lua_State* L)
367 #ifndef LUABIND_NO_ERROR_CHECKING
369 if (lua_gettop(L) != 1 || lua_type(L, 1) != LUA_TSTRING || lua_isnumber(L, 1))
371 lua_pushstring(L, "invalid construct, expected class name");
372 lua_error(L);
375 #endif
377 const char* name = lua_tostring(L, 1);
379 void* c = lua_newuserdata(L, sizeof(class_rep));
381 lua_pushvalue(L, -1);
382 // the global name of the class is registered inside this constructor
383 new(c) class_rep(L, name);
384 lua_pushcclosure(L, &stage2, 1);
386 return 1;
390 template<class Type>
391 struct register_wrapped_type
393 template<class Signature, class Policies>
394 static void apply(detail::construct_rep::overload_t& o, const Signature*, const Policies*)
396 o.set_wrapped_constructor(
397 &detail::construct_wrapped_class<Type, Policies, Signature>::apply
402 template<>
403 struct register_wrapped_type<detail::null_type>
405 template<class Signature, class Policies>
406 static void apply(detail::construct_rep::overload_t&, const Signature*, const Policies*) {}
410 // if the class is held by a smart pointer, we need to be able to
411 // implicitly dereference the pointer when needed.
413 template<class UnderlyingT, class HeldT>
414 struct extract_underlying_type
416 static void* extract(void* ptr)
418 HeldT& held_obj = *reinterpret_cast<HeldT*>(ptr);
419 UnderlyingT* underlying_ptr = get_pointer(held_obj);
420 return underlying_ptr;
424 template<class HeldType>
425 struct internal_new_crep
427 template<class T>
428 static void apply(detail::class_rep* crep, const char* name, lua_State* L, detail::class_registry* r, detail::type<T>)
430 new(crep) detail::class_rep(LUABIND_TYPEID(T),
431 name,
433 detail::destructor_s<T>::apply,
434 LUABIND_TYPEID(HeldType),
435 detail::extract_underlying_type<
436 T, HeldType>::extract);
438 if (r->classes.find(LUABIND_TYPEID(HeldType)) == r->classes.end())
440 r->classes[LUABIND_TYPEID(HeldType)] = crep;
445 template<>
446 struct internal_new_crep<detail::null_type>
448 template<class T>
449 static void apply(detail::class_rep* crep, const char* name, lua_State* L, detail::class_registry* r, detail::type<T>)
451 new(crep) detail::class_rep(LUABIND_TYPEID(T),
452 name,
454 detail::destructor_s<T>::apply,
455 LUABIND_INVALID_TYPE_INFO,
460 } // detail
462 // registers a class in the lua environment
463 template<class T, class X1, class X2, class X3>
464 struct class_
466 typedef class_<T, X1, X2, X3> self_t;
468 private:
469 template<class A, class B, class C, class D>
470 class_(const class_<A,B,C,D>&);
471 public:
473 // WrappedType MUST inherit from T
474 typedef typename detail::extract_parameter<
475 boost::mpl::vector3<X1,X2,X3>
476 , boost::is_base_and_derived<T, boost::mpl::_>
477 /* , boost::mpl::not_<
478 boost::mpl::or_<
479 detail::is_bases<boost::mpl::_>
480 , boost::is_base_and_derived<boost::mpl::_, T>
483 , detail::null_type
484 >::type WrappedType;
486 typedef typename detail::extract_parameter<
487 boost::mpl::vector3<X1,X2,X3>
488 , boost::mpl::not_<
489 boost::mpl::or_<
490 boost::mpl::or_<
491 detail::is_bases<boost::mpl::_>
492 , boost::is_base_and_derived<boost::mpl::_, T>
494 , boost::is_base_and_derived<T, boost::mpl::_>
497 , detail::null_type
498 >::type HeldType;
500 lua_State* L;
501 const char* name;
502 detail::class_rep* m_crep;
504 // this function generates conversion information
505 // in the given class_rep structure. It will be able
506 // to implicitly cast to the given template type
507 template<class To>
508 static void gen_base_info(detail::class_rep* crep, detail::class_registry* registry, detail::type<To>)
510 // fist, make sure the given base class is registered.
511 // if it's not registered we can't push it's lua table onto
512 // the stack because it doesn't have a table
514 // If you hit this assert you are deriving from a type that is not registered
515 // in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
516 // Please note that if you don't need to have access to the base class or the
517 // conversion from the derived class to the base class, you don't need
518 // to tell luabind that it derives.
519 assert(registry->find_class(LUABIND_TYPEID(To)) && "You cannot derive from an unregistered type");
521 // try to cast this type to the base type and remember
522 // the pointer offset. For multiple inheritance the pointer
523 // may change when casting. Since we need to be able to
524 // cast we need this pointer offset.
525 // store the information in this class' base class-vector
526 detail::class_rep::base_info base;
527 base.base = registry->find_class(LUABIND_TYPEID(To));
528 T* null_pointer = reinterpret_cast<T*>(1); // this wont work if the pointer is 0!
529 base.pointer_offset = static_cast<int>((reinterpret_cast<char*>(static_cast<To*>(null_pointer)) - reinterpret_cast<char*>(null_pointer)));
530 crep->add_base(base);
533 static void gen_base_info(detail::class_rep*, detail::class_registry*, detail::type<detail::null_type>)
536 #define LUABIND_GEN_BASE_INFO(z, n, text) gen_base_info(crep, reg, detail::type<B##n>());
538 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, class B)>
539 static void generate_baseclass_list(detail::class_rep* crep, detail::class_registry* reg, detail::type<bases<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, B)> >)
541 BOOST_PP_REPEAT(LUABIND_MAX_BASES, LUABIND_GEN_BASE_INFO, _)
544 #undef LUABIND_GEN_BASE_INFO
546 // this is the internal version of def() it is run from both overloads
547 // of def. It has two versions, one where a contstructor is registered
548 // and one where a function is registered
549 template<class Policies>
550 struct internal_def_s
552 template<class F>
553 static void apply(const char* name, F f, detail::class_rep* crep)
555 // std::cout << "HeldType2: " << typeid(HeldType).name() << "\n";
557 detail::overload_rep o(f, static_cast<Policies*>(0));
559 typedef LUABIND_MSVC_TYPENAME detail::function_callback_s<HeldType,T,F,Policies>::type call_t;
561 o.set_match_fun(&detail::match_function_callback_s<T,F,Policies>::apply);
562 o.call_fun = boost::bind<int>(call_t(f), _1, _2);
564 #ifndef LUABIND_NO_ERROR_CHECKING
566 o.set_sig_fun(&detail::get_member_signature<F>::apply);
568 #endif
570 crep->add_function(name, o);
573 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)>
574 static void apply(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>, detail::class_rep* crep)
576 // std::cout << "HeldType2: " << typeid(HeldType).name() << "\n";
578 detail::construct_rep::overload_t o;
580 o.set_constructor(
581 &detail::construct_class<
583 ,Policies
584 ,constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>
585 >::apply
588 // if we have a WrappedType, we have to register it's constructor
589 // but if it's null_type (no WrappedType) we should not register it
590 detail::register_wrapped_type<WrappedType>::apply(o,
591 static_cast<const constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>*>(0),
592 static_cast<const Policies*>(0));
595 o.set_match_fun(
596 &detail::constructor_match<
597 constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>
599 ,Policies
600 >::apply);
602 #ifndef LUABIND_NO_ERROR_CHECKING
604 o.set_sig_fun(&detail::get_signature<constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> >::apply);
606 #endif
608 typedef constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> con_t;
610 o.set_arity(detail::calc_arity<con_t::arity>::apply(con_t(), static_cast<Policies*>(0)));
612 crep->add_constructor(o);
616 class_(lua_State* L_, const char* name_): L(L_), name(name_)
619 std::cout << "X1: " << typeid(X1).name() << "\n";
620 std::cout << "X2: " << typeid(X2).name() << "\n";
621 std::cout << "X3: " << typeid(X3).name() << "\n";
622 std::cout << "HeldType1: " << typeid(HeldType).name() << "\n";
624 detail::class_registry* r = detail::class_registry::get_registry(L);
625 // create a class_rep structure for this class.
626 // allocate it within lua to let lua collect it on
627 // lua_close(). This is better than allocating it
628 // as a static, since it will then be destructed
629 // when the program exits instead.
630 // warning: we assume that lua will not
631 // move the userdata memory.
632 lua_newuserdata(L, sizeof(detail::class_rep));
633 m_crep = reinterpret_cast<detail::class_rep*>(lua_touserdata(L, -1));
635 detail::internal_new_crep<HeldType>::apply(m_crep, name, L, r, detail::type<T>());
637 typedef typename detail::extract_parameter<
638 boost::mpl::vector3<X1,X2,X3>
639 , boost::mpl::or_<
640 detail::is_bases<boost::mpl::_>
641 , boost::is_base_and_derived<boost::mpl::_, T>
643 , no_bases
644 >::type bases_t;
646 typedef typename
647 boost::mpl::if_<detail::is_bases<bases_t>
648 , bases_t
649 , bases<bases_t>
650 >::type Base;
652 generate_baseclass_list(m_crep, r, detail::type<Base>());
654 // register this new type in the class registry
655 r->add_class(LUABIND_TYPEID(T), m_crep);
657 // std::cout << "held type: " << typeid(HeldType).name() << '\n';
660 template<class F>
661 class_& def(const char* name, F f)
663 internal_def_s<detail::null_type>::apply(name, f, m_crep);
664 return *this;
667 template<class F, class Policies>
668 class_& def(const char* name, F f, const Policies&)
670 internal_def_s<Policies>::apply(name, f, m_crep);
671 return *this;
674 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)>
675 class_& def(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> sig)
677 internal_def_s<detail::null_type>::apply(sig, m_crep);
678 return *this;
681 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A), class Policies>
682 class_& def(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> sig, const Policies& policies)
684 internal_def_s<Policies>::apply(sig, m_crep);
685 return *this;
688 #ifndef BOOST_MSVC
690 template<class Getter, class Head, class Tail>
691 class_& property(const char* name, Getter g, const detail::policy_cons<Head,Tail>& policies)
693 typedef detail::policy_cons<Head,Tail> policies_t;
695 m_crep->add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, policies_t>(policies), _1, _2, g));
696 return *this;
699 #endif
701 template<class Getter, class Setter>
702 class_& property(const char* name, Getter g, Setter s)
704 m_crep->add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, detail::null_type>(), _1, _2, g));
705 m_crep->add_setter(name, boost::bind<int>(detail::set_caller<T, Setter, detail::null_type>(), _1, _2, s));
706 return *this;
709 template<class Getter, class Setter, class H1, class T1>
710 class_& property(const char* name, Getter g, Setter s, const detail::policy_cons<H1,T1>& get_policies)
712 typedef detail::policy_cons<H1,T1> get_policies_t;
714 m_crep->add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, get_policies_t>(get_policies), _1, _2, g));
715 m_crep->add_setter(name, boost::bind<int>(detail::set_caller<T, Setter, detail::null_type>(), _1, _2, s));
716 return *this;
719 template<class Getter, class Setter, class H2, class T2>
720 class_& property(const char* name
721 , Getter g, Setter s
722 , const detail::null_type&
723 , const detail::policy_cons<H2,T2>& set_policies)
725 typedef detail::policy_cons<H2,T2> set_policies_t;
727 m_crep->add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, detail::null_type>(), _1, _2, g));
728 m_crep->add_setter(name, boost::bind<int>(detail::set_caller<T, Setter, set_policies_t>(set_policies), _1, _2, s));
729 return *this;
732 template<class Getter, class Setter, class H1, class T1, class H2, class T2>
733 class_& property(const char* name
734 , Getter g, Setter s
735 , const detail::policy_cons<H1,T1>& get_policies
736 , const detail::policy_cons<H2,T2>& set_policies)
738 typedef detail::policy_cons<H1,T1> get_policies_t;
739 typedef detail::policy_cons<H2,T2> set_policies_t;
741 m_crep->add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, get_policies_t>(get_policies), _1, _2, g));
742 m_crep->add_setter(name, boost::bind<int>(detail::set_caller<T, Setter, set_policies_t>(set_policies), _1, _2, s));
743 return *this;
746 template<class Getter>
747 class_& property(const char* name, Getter g)
749 m_crep->add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, detail::null_type>(), _1, _2, g));
750 return *this;
753 template<class D>
754 class_& def_readonly(const char* name, D T::*member_ptr)
756 m_crep->add_getter(name, boost::bind<int>(detail::auto_get<T,D,detail::null_type>(), _1, _2, member_ptr));
757 return *this;
760 template<class D, class Policies>
761 class_& def_readonly(const char* name, D T::*member_ptr, const Policies& policies)
763 m_crep->add_getter(name, boost::bind<int>(detail::auto_get<T,D,Policies>(policies), _1, _2, member_ptr));
764 return *this;
767 template<class D>
768 class_& def_readwrite(const char* name, D T::*member_ptr)
770 m_crep->add_getter(name, boost::bind<int>(detail::auto_get<T,D,detail::null_type>(), _1, _2, member_ptr));
771 m_crep->add_setter(name, boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr));
772 return *this;
775 template<class D, class GetPolicies>
776 class_& def_readwrite(const char* name, D T::*member_ptr, const GetPolicies& get_policies)
778 m_crep->add_getter(name, boost::bind<int>(detail::auto_get<T,D,GetPolicies>(get_policies), _1, _2, member_ptr));
779 m_crep->add_setter(name, boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr));
780 return *this;
783 template<class D, class GetPolicies, class SetPolicies>
784 class_& def_readwrite(const char* name, D T::*member_ptr, const GetPolicies& get_policies, const SetPolicies& set_policies)
786 m_crep->add_getter(name, boost::bind<int>(detail::auto_get<T,D,GetPolicies>(get_policies), _1, _2, member_ptr));
787 m_crep->add_setter(name, boost::bind<int>(detail::auto_set<T,D,SetPolicies>(set_policies), _1, _2, member_ptr));
788 return *this;
791 template<class op_id, class Left, class Right, class Policies>
792 class_& def(detail::operator_<op_id, Left, Right>, const Policies& policies)
794 typedef typename detail::operator_unwrapper<Policies, op_id, T, Left, Right> op_type;
795 #ifndef LUABIND_NO_ERROR_CHECKING
796 m_crep->add_operator(L
797 , op_type::get_id()
798 , &op_type::execute
799 , &op_type::match
800 , &detail::get_signature<constructor<typename op_type::left_t, typename op_type::right_t> >::apply
801 , detail::is_unary(op_type::get_id()) ? 1 : 2);
802 #else
803 m_crep->add_operator(L
804 , op_type::get_id()
805 , &op_type::execute
806 , &op_type::match
807 , detail::is_unary(op_type::get_id()) ? 1 : 2);
808 #endif
809 return *this;
812 template<class op_id, class Left, class Right>
813 class_& def(detail::operator_<op_id, Left, Right>)
815 typedef typename detail::operator_unwrapper<detail::null_type, op_id, T, Left, Right> op_type;
817 #ifndef LUABIND_NO_ERROR_CHECKING
818 m_crep->add_operator(L
819 , op_type::get_id()
820 , &op_type::execute
821 , &op_type::match
822 , &detail::get_signature<constructor<LUABIND_MSVC_TYPENAME op_type::left_t, LUABIND_MSVC_TYPENAME op_type::right_t> >::apply
823 , detail::is_unary(op_type::get_id()) ? 1 : 2);
824 #else
825 m_crep->add_operator(L
826 , op_type::get_id()
827 , &op_type::execute
828 , &op_type::match
829 , detail::is_unary(op_type::get_id()) ? 1 : 2);
830 #endif
831 return *this;
834 template<class Signature, bool Constant>
835 class_& def(detail::application_operator<Signature, Constant>*)
837 typedef detail::application_operator<Signature, Constant, detail::null_type> op_t;
839 int arity = detail::calc_arity<Signature::arity>::apply(Signature(), static_cast<detail::null_type*>(0));
841 #ifndef LUABIND_NO_ERROR_CHECKING
842 m_crep->add_operator(L, detail::op_call, &op_t::template apply<T>::execute, &op_t::match, &detail::get_signature<Signature>::apply, arity + 1);
843 #else
844 m_crep->add_operator(L, detail::op_call, &op_t::template apply<T>::execute, &op_t::match, arity + 1);
845 #endif
847 return *this;
850 template<class Signature, bool Constant, class Policies>
851 class_& def(detail::application_operator<Signature, Constant>*, const Policies& policies)
853 typedef detail::application_operator<Signature, Constant, Policies> op_t;
855 int arity = detail::calc_arity<Signature::arity>::apply(Signature(), static_cast<Policies*>(0));
857 #ifndef LUABIND_NO_ERROR_CHECKING
859 m_crep->add_operator(L, detail::op_call, &op_t::template apply<T>::execute, &op_t::match, &detail::get_signature<Signature>::apply, arity + 1);
860 #else
861 m_crep->add_operator(L, detail::op_call, &op_t::template apply<T>::execute, &op_t::match, arity + 1);
862 #endif
864 return *this;
867 detail::enum_maker<self_t> enum_(const char*)
869 return detail::enum_maker<self_t>(*this);
875 #endif // LUABIND_CLASS_HPP_INCLUDED