From 87898f6012d553d7fe783ac1329ca47d45d262a7 Mon Sep 17 00:00:00 2001 From: Daniel Wallin Date: Mon, 8 Aug 2011 10:58:17 +0200 Subject: [PATCH] Initial C++0x support. Variadic templates replace most of the PP repetition. Work in progress. --- luabind/class.hpp | 53 +++++++- luabind/config.hpp | 9 ++ luabind/detail/call.hpp | 9 +- luabind/detail/call_0x.hpp | 259 ++++++++++++++++++++++++++++++++++++ luabind/detail/call_function.hpp | 116 +++++++++++++++- luabind/detail/call_member.hpp | 70 +++++++++- luabind/detail/class_rep.hpp | 1 - luabind/detail/constructor.hpp | 41 +++++- luabind/detail/deduce_signature.hpp | 91 +++++++++++-- luabind/detail/format_signature.hpp | 33 +++++ luabind/detail/policy.hpp | 1 + luabind/detail/signature_match.hpp | 29 ++-- luabind/make_function.hpp | 5 +- luabind/object.hpp | 58 ++++++++ luabind/operator.hpp | 52 +++++++- luabind/tag_function.hpp | 47 +++++-- luabind/vector.hpp | 125 +++++++++++++++++ luabind/wrapper_base.hpp | 50 ++++++- test/Jamfile | 1 + 19 files changed, 996 insertions(+), 54 deletions(-) create mode 100644 luabind/detail/call_0x.hpp create mode 100644 luabind/vector.hpp diff --git a/luabind/class.hpp b/luabind/class.hpp index b339115..b8fd361 100644 --- a/luabind/class.hpp +++ b/luabind/class.hpp @@ -71,14 +71,13 @@ #include #include -#include -#include #include -#include +#ifndef LUABIND_CPP0x #include #include #include +#endif #include #include #include @@ -87,6 +86,7 @@ #include #include #include +#include #include #include @@ -153,6 +153,16 @@ namespace luabind return 0; } +# ifdef LUABIND_CPP0x + + template + struct bases + {}; + + typedef bases<> no_bases; + +# else + template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( LUABIND_MAX_BASES, class A, detail::null_type) @@ -162,6 +172,8 @@ namespace luabind typedef bases no_bases; +# endif // LUABIND_CPP0x + namespace detail { template @@ -169,10 +181,17 @@ namespace luabind : mpl::false_ {}; +# ifdef LUABIND_CPP0x + template + struct is_bases > + : mpl::true_ + {}; +# else template struct is_bases > : mpl::true_ {}; +# endif template struct is_unspecified @@ -565,6 +584,8 @@ namespace luabind void gen_base_info(detail::type_) {} +# ifndef LUABIND_CPP0x + #define LUABIND_GEN_BASE_INFO(z, n, text) gen_base_info(detail::type_()); template @@ -575,6 +596,20 @@ namespace luabind #undef LUABIND_GEN_BASE_INFO +# else // !LUABIND_CPP0x + + template + void ignore(Args&&...) + {} + + template + void generate_baseclass_list(detail::type_ >) + { + ignore((gen_base_info(detail::type_()), 0)...); + } + +# endif // !LUABIND_CPP0x + class_(const char* name): class_base(name), scope(*this) { #ifndef NDEBUG @@ -609,6 +644,16 @@ namespace luabind , policies, boost::mpl::false_()); } +# ifdef LUABIND_CPP0x + + template + class_& def(constructor, Policies const& policies = Policies()) + { + return this->def_constructor((constructor*)0, policies); + } + +# else + template class_& def(constructor sig) { @@ -621,6 +666,8 @@ namespace luabind return this->def_constructor(&sig, policies); } +# endif // LUABIND_CPP0x + template class_& property(const char* name, Getter g) { diff --git a/luabind/config.hpp b/luabind/config.hpp index e8eea87..d72daa7 100644 --- a/luabind/config.hpp +++ b/luabind/config.hpp @@ -118,6 +118,15 @@ namespace std # define LUABIND_API #endif +#if !defined(LUABIND_CPP0x) \ + && !defined(BOOST_NO_DECLTYPE) \ + && !defined(BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS) \ + && !defined(BOOST_NO_VARIADIC_TEMPLATES) + +# define LUABIND_CPP0x + +#endif + namespace luabind { LUABIND_API void disable_super_deprecation(); diff --git a/luabind/detail/call.hpp b/luabind/detail/call.hpp index 0737973..265a437 100644 --- a/luabind/detail/call.hpp +++ b/luabind/detail/call.hpp @@ -7,6 +7,12 @@ # ifndef LUABIND_CALL2_080911_HPP # define LUABIND_CALL2_080911_HPP +# include + +# ifdef LUABIND_CPP0x +# include +# else + # include # include # include @@ -20,7 +26,6 @@ # include # include -# include # include # include @@ -192,6 +197,8 @@ inline int sum_scores(int const* first, int const* last) }} // namespace luabind::detail +# endif // LUABIND_CPP0x + # endif // LUABIND_CALL2_080911_HPP #else // BOOST_PP_IS_ITERATING diff --git a/luabind/detail/call_0x.hpp b/luabind/detail/call_0x.hpp new file mode 100644 index 0000000..8ce42ca --- /dev/null +++ b/luabind/detail/call_0x.hpp @@ -0,0 +1,259 @@ +// Copyright Daniel Wallin 2010. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_DETAIL_CALL_0X_100630_HPP +# define LUABIND_DETAIL_CALL_0X_100630_HPP + +# include +# include +# include +# include +# include +# include + +namespace luabind { namespace detail { + +struct invoke_context; + +struct LUABIND_API function_object +{ + function_object(lua_CFunction entry) + : entry(entry) + , next(0) + {} + + virtual ~function_object() + {} + + virtual int call( + lua_State* L, invoke_context& ctx) const = 0; + virtual void format_signature(lua_State* L, char const* function) const = 0; + + lua_CFunction entry; + std::string name; + function_object* next; + object keepalive; +}; + +struct LUABIND_API invoke_context +{ + invoke_context() + : best_score((std::numeric_limits::max)()) + , candidate_index(0) + {} + + operator bool() const + { + return candidate_index == 1; + } + + void format_error(lua_State* L, function_object const* overloads) const; + + int best_score; + function_object const* candidates[10]; + int candidate_index; +}; + +template +inline int invoke( + lua_State* L, function_object const& self, invoke_context& ctx + , F const& f, vector, Policies const& policies) +{ + return invoke_aux( + L, self, ctx, f, policies, vector() + , typename make_index_tuple::type() + ); +} + +template +struct make_arg_converter +{ + typedef typename find_conversion_policy::type generator; + typedef typename mpl::apply_wrap2::type type; +}; + +template +struct make_result_converter +{ + typedef typename find_conversion_policy<0, Policies>::type generator; + typedef typename mpl::apply_wrap2::type type; +}; + +struct void_result +{}; + +template +struct make_result_converter +{ + typedef void_result type; +}; + +template +inline int invoke_aux( + lua_State* L, function_object const& self, invoke_context& ctx + , F const& f, Policies const& policies + , vector, index_tuple) +{ + typename make_result_converter::type result_converter; + + return invoke_actual( + L, self, ctx, f, policies + , vector(), index_tuple(), result_converter + , typename make_arg_converter::type()... + ); +} + +inline int sum_scores(int const* first, int const* last) +{ + int result = 0; + + for (; first != last; ++first) + { + if (*first < 0) + return *first; + result += *first; + } + + return result; +} + +template +int compute_score(lua_State* L, Converter& converter, int index) +{ + return converter.match(L, LUABIND_DECORATE_TYPE(T), index); +} + +inline int compute_indices(int*, int base) +{ + return base; +} + +template +int compute_indices( + int* target, int base, Converter& converter, Rest&... rest) +{ + *target = base; + return compute_indices(target + 1, base + converter.consumed_args(), rest...); +} + +template +void invoke_function( + lua_State* L, F const& f, std::false_type, ResultConverter& result_converter + , Args&&... args) +{ + result_converter.apply(L, f(std::forward(args)...)); +} + +template +void invoke_function( + lua_State* L, F const& f, std::false_type, void_result, Args&&... args) +{ + f(std::forward(args)...); +} + +template +void invoke_function( + lua_State* L, F const& f, std::true_type, ResultConverter& result_converter + , This&& this_, Args&&... args) +{ + result_converter.apply(L, (this_.*f)(std::forward(args)...)); +} + +template +void invoke_function( + lua_State* L, F const& f, std::true_type, void_result, This&& this_, Args&&... args) +{ + (this_.*f)(std::forward(args)...); +} + +inline int maybe_yield_aux(lua_State*, int results, mpl::false_) +{ + return results; +} + +inline int maybe_yield_aux(lua_State* L, int results, mpl::true_) +{ + return lua_yield(L, results); +} + +template +int maybe_yield(lua_State* L, int results, Policies*) +{ + return maybe_yield_aux( + L, results, has_policy()); +} + +// Helper that ignores everything passed to it. Used so that we can invoke +// postcall on converters in a parameter pack expansion. +template +void ignore(T&&...) +{} + +template < + class F, class Policies, class R, class... Args, int... Indices + , class ResultConverter, class... Converters +> +inline int invoke_actual( + lua_State* L, function_object const& self, invoke_context& ctx + , F const& f, Policies const& policies + , vector, index_tuple + , ResultConverter& result_converter, Converters&&... converters) +{ + int indices[sizeof...(Args) + 1]; + int const arity = compute_indices(indices + 1, 1, converters...) - 1; + + int const arguments = lua_gettop(L); + int score = -1; + + if (arity == arguments) + { + int const scores[] = { + compute_score(L, converters, indices[Indices + 1])... + }; + + score = sum_scores(scores, scores + sizeof...(Args)); + } + + if (score >= 0 && score < ctx.best_score) + { + ctx.best_score = score; + ctx.candidates[0] = &self; + ctx.candidate_index = 1; + } + else if (score == ctx.best_score) + { + ctx.candidates[ctx.candidate_index++] = &self; + } + + int results = 0; + + if (self.next) + { + results = self.next->call(L, ctx); + } + + if (score == ctx.best_score && ctx.candidate_index == 1) + { + invoke_function( + L, f, std::is_member_function_pointer(), result_converter + , converters.apply(L, LUABIND_DECORATE_TYPE(Args), indices[Indices + 1])... + ); + + ignore( + (converters.converter_postcall( + L, LUABIND_DECORATE_TYPE(Args), indices[Indices + 1]), 0)... + ); + + results = maybe_yield(L, lua_gettop(L) - arguments, (Policies*)0); + indices[0] = arguments + results; + + policy_list_postcall::apply(L, indices); + } + + return results; +} + +}} // namespace luabind::detail + +#endif // LUABIND_DETAIL_CALL_0X_100630_HPP diff --git a/luabind/detail/call_function.hpp b/luabind/detail/call_function.hpp index f0d455b..d8520e5 100644 --- a/luabind/detail/call_function.hpp +++ b/luabind/detail/call_function.hpp @@ -31,12 +31,14 @@ #include #include #include -#include -#include -#include -#include -#include -#include +#ifndef LUABIND_CPP0x +# include +# include +# include +# include +# include +# include +#endif #include #include @@ -89,7 +91,11 @@ namespace luabind int top = lua_gettop(L); push_args_from_tuple<1>::apply(L, m_args); +# ifdef LUABIND_CPP0x + if (m_fun(L, std::tuple_size::value, 0)) +# else if (m_fun(L, boost::tuples::length::value, 0)) +# endif { assert(lua_gettop(L) == top - m_params + 1); #ifndef LUABIND_NO_EXCEPTIONS @@ -119,7 +125,11 @@ namespace luabind int top = lua_gettop(L); push_args_from_tuple<1>::apply(L, m_args); +# ifdef LUABIND_CPP0x + if (m_fun(L, std::tuple_size::value, 1)) +# else if (m_fun(L, boost::tuples::length::value, 1)) +# endif { assert(lua_gettop(L) == top - m_params + 1); #ifndef LUABIND_NO_EXCEPTIONS @@ -165,7 +175,11 @@ namespace luabind int top = lua_gettop(L); detail::push_args_from_tuple<1>::apply(L, m_args, p); +# ifdef LUABIND_CPP0x + if (m_fun(L, std::tuple_size::value, 1)) +# else if (m_fun(L, boost::tuples::length::value, 1)) +# endif { assert(lua_gettop(L) == top - m_params + 1); #ifndef LUABIND_NO_EXCEPTIONS @@ -215,7 +229,6 @@ namespace luabind template class proxy_function_void_caller { - friend class luabind::object; public: typedef int(*function_t)(lua_State*, int, int); @@ -253,7 +266,11 @@ namespace luabind int top = lua_gettop(L); push_args_from_tuple<1>::apply(L, m_args); +# ifdef LUABIND_CPP0x + if (m_fun(L, std::tuple_size::value, 0)) +# else if (m_fun(L, boost::tuples::length::value, 0)) +# endif { assert(lua_gettop(L) == top - m_params + 1); #ifndef LUABIND_NO_EXCEPTIONS @@ -280,7 +297,11 @@ namespace luabind int top = lua_gettop(L); detail::push_args_from_tuple<1>::apply(L, m_args, p); +# ifdef LUABIND_CPP0x + if (m_fun(L, std::tuple_size::value, 0)) +# else if (m_fun(L, boost::tuples::length::value, 0)) +# endif { assert(lua_gettop(L) == top - m_params + 1); #ifndef LUABIND_NO_EXCEPTIONS @@ -310,9 +331,90 @@ namespace luabind } +# ifdef LUABIND_CPP0x + + +namespace detail +{ + + template + struct make_proxy + { + typedef proxy_function_caller > type; + }; + + template + struct make_proxy + { + typedef proxy_function_void_caller > type; + }; + +} // namespace detail + +template +typename detail::make_proxy::type call_function( + lua_State* L, char const* name, Args const&... args) +{ + assert(name && "luabind::call_function() expects a function name"); + + lua_pushstring(L, name); + lua_gettable(L, LUA_GLOBALSINDEX); + + typedef typename detail::make_proxy::type proxy_type; + return proxy_type(L, 1, &detail::pcall, std::tuple(&args...)); +} + +template +typename detail::make_proxy::type call_function( + object const& obj, Args const&... args) +{ + obj.push(obj.interpreter()); + + typedef typename detail::make_proxy::type proxy_type; + return proxy_type( + obj.interpreter(), 1, &detail::pcall, std::tuple(&args...)); +} + +template +typename detail::make_proxy::type resume_function( + lua_State* L, char const* name, Args const&... args) +{ + assert(name && "luabind::call_function() expects a function name"); + + lua_pushstring(L, name); + lua_gettable(L, LUA_GLOBALSINDEX); + + typedef typename detail::make_proxy::type proxy_type; + return proxy_type(L, 1, &detail::resume_impl, std::tuple(&args...)); +} + +template +typename detail::make_proxy::type resume_function( + object const& obj, Args const&... args) +{ + obj.push(obj.interpreter()); + + typedef typename detail::make_proxy::type proxy_type; + return proxy_type( + obj.interpreter(), 1, &detail::resume_impl, std::tuple(&args...)); +} + +template +typename detail::make_proxy::type resume( + lua_State* L, Args const&... args) +{ + typedef typename detail::make_proxy::type proxy_type; + return proxy_type( + L, 0, &detail::resume_impl, std::tuple(&args...)); +} + +# else // LUABIND_CPP0x + #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, , 1)) #include BOOST_PP_ITERATE() +# endif // LUABIND_CPP0x + } #endif // LUABIND_CALL_FUNCTION_HPP_INCLUDED diff --git a/luabind/detail/call_member.hpp b/luabind/detail/call_member.hpp index 7fdbd50..6e1bf9c 100644 --- a/luabind/detail/call_member.hpp +++ b/luabind/detail/call_member.hpp @@ -33,11 +33,13 @@ #include #include // TODO: REMOVE DEPENDENCY -#include +#ifndef LUABIND_CPP0x +# include -#include -#include -#include +# include +# include +# include +#endif #include @@ -84,7 +86,11 @@ namespace luabind // and all the parameters push_args_from_tuple<1>::apply(L, m_args); +# ifdef LUABIND_CPP0x + if (pcall(L, std::tuple_size::value + 1, 0)) +# else if (pcall(L, boost::tuples::length::value + 1, 0)) +# endif { assert(lua_gettop(L) == top + 1); #ifndef LUABIND_NO_EXCEPTIONS @@ -115,7 +121,11 @@ namespace luabind // pcall will pop the function and self reference // and all the parameters push_args_from_tuple<1>::apply(L, m_args); +# ifdef LUABIND_CPP0x + if (pcall(L, std::tuple_size::value + 1, 1)) +# else if (pcall(L, boost::tuples::length::value + 1, 1)) +# endif { assert(lua_gettop(L) == top + 1); #ifndef LUABIND_NO_EXCEPTIONS @@ -167,7 +177,11 @@ namespace luabind // and all the parameters detail::push_args_from_tuple<1>::apply(L, m_args, p); +# ifdef LUABIND_CPP0x + if (pcall(L, std::tuple_size::value + 1, 1)) +# else if (pcall(L, boost::tuples::length::value + 1, 1)) +# endif { assert(lua_gettop(L) == top + 1); #ifndef LUABIND_NO_EXCEPTIONS @@ -247,7 +261,11 @@ namespace luabind // and all the parameters push_args_from_tuple<1>::apply(L, m_args); +# ifdef LUABIND_CPP0x + if (pcall(L, std::tuple_size::value + 1, 0)) +# else if (pcall(L, boost::tuples::length::value + 1, 0)) +# endif { assert(lua_gettop(L) == top + 1); #ifndef LUABIND_NO_EXCEPTIONS @@ -278,7 +296,11 @@ namespace luabind // and all the parameters detail::push_args_from_tuple<1>::apply(L, m_args, p); +# ifdef LUABIND_CPP0x + if (pcall(L, std::tuple_size::value + 1, 0)) +# else if (pcall(L, boost::tuples::length::value + 1, 0)) +# endif { assert(lua_gettop(L) == top + 1); #ifndef LUABIND_NO_EXCEPTIONS @@ -305,9 +327,49 @@ namespace luabind } // detail +# ifdef LUABIND_CPP0x + +namespace detail +{ + + template + struct make_member_proxy + { + typedef proxy_member_caller > type; + }; + + template + struct make_member_proxy + { + typedef proxy_member_void_caller > type; + }; + +} // namespace detail + +template +typename detail::make_member_proxy::type call_member( + object const& obj, char const* name, Args const&... args) +{ + // get the function + obj.push(obj.interpreter()); + lua_pushstring(obj.interpreter(), name); + lua_gettable(obj.interpreter(), -2); + // duplicate the self-object + lua_pushvalue(obj.interpreter(), -2); + // remove the bottom self-object + lua_remove(obj.interpreter(), -3); + + typedef typename detail::make_member_proxy::type proxy_type; + return proxy_type(obj.interpreter(), std::tuple(&args...)); +} + +# else // LUABIND_CPP0x + #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, , 1)) #include BOOST_PP_ITERATE() +# endif + } #endif // LUABIND_CALL_MEMBER_HPP_INCLUDED diff --git a/luabind/detail/class_rep.hpp b/luabind/detail/class_rep.hpp index 1f825db..854a4be 100644 --- a/luabind/detail/class_rep.hpp +++ b/luabind/detail/class_rep.hpp @@ -25,7 +25,6 @@ #define LUABIND_CLASS_REP_HPP_INCLUDED #include -#include #include #include diff --git a/luabind/detail/constructor.hpp b/luabind/detail/constructor.hpp index f0f8104..d8d5460 100644 --- a/luabind/detail/constructor.hpp +++ b/luabind/detail/constructor.hpp @@ -12,10 +12,12 @@ # include # include -# include -# include -# include -# include +# ifndef LUABIND_CPP0x +# include +# include +# include +# include +# endif namespace luabind { namespace detail { @@ -28,6 +30,35 @@ void inject_backref(lua_State* L, T* p, wrap_base*) weak_ref(get_main_thread(L), L, 1).swap(wrap_access::ref(*p)); } +# ifdef LUABIND_CPP0x + +template +struct construct; + +template +struct construct > +{ + typedef pointer_holder holder_type; + + void operator()(argument const& self_, Args... args) const + { + object_rep* self = touserdata(self_); + + std::auto_ptr instance(new T(args...)); + inject_backref(self_.interpreter(), instance.get(), instance.get()); + + void* naked_ptr = instance.get(); + Pointer ptr(instance.release()); + + void* storage = self->allocate(sizeof(holder_type)); + + self->set_instance(new (storage) holder_type( + ptr, registered_class::id, naked_ptr)); + } +}; + +# else // LUABIND_CPP0x + template struct construct_aux; @@ -62,6 +93,8 @@ struct construct_aux<0, T, Pointer, Signature> (3, (1, LUABIND_MAX_ARITY, )) # include BOOST_PP_ITERATE() +# endif // LUABIND_CPP0x + }} // namespace luabind::detail # endif // LUABIND_DETAIL_CONSTRUCTOR_081018_HPP diff --git a/luabind/detail/deduce_signature.hpp b/luabind/detail/deduce_signature.hpp index e47e22f..a2160ea 100644 --- a/luabind/detail/deduce_signature.hpp +++ b/luabind/detail/deduce_signature.hpp @@ -8,18 +8,91 @@ # define LUABIND_DEDUCE_SIGNATURE_080911_HPP # include - -# if LUABIND_MAX_ARITY <= 8 -# include -# else -# include +# include + +# ifndef LUABIND_CPP0x +# if LUABIND_MAX_ARITY <= 8 +# include +# else +# include +# endif +# include +# include +# include # endif -# include -# include -# include namespace luabind { namespace detail { +# ifdef LUABIND_CPP0x + +template +vector deduce_signature(R(*)(Args...), ...) +{ + return vector(); +} + +template +vector deduce_signature(R(T::*)(Args...)) +{ + return vector(); +} + +template +vector::type&, Args...> +deduce_signature(R(T::*)(Args...), Wrapped*) +{ + return vector::type&, Args...>(); +} + +template +vector deduce_signature(R(T::*)(Args...) const) +{ + return vector(); +} + +template +vector::type const&, Args...> +deduce_signature(R(T::*)(Args...) const, Wrapped*) +{ + return vector::type const&, Args...>(); +} + +// This is primarily intended to catch C++0x lambda closures. It figures out +// the signature of a function object, and strips the object type from the +// resulting signature: +// +// vector +// +// into +// +// vector +// +// This overload is all luabind needs to correctly handle monomorphic function +// objects with a fixed signature such as C++0x lambdas. The standard doesn't +// explicitly say that an implementation isn't allowed to add additional +// overloads of operator() to the closure type, in practice however, noone +// seems to. + +template +struct strip_this_argument; + +template +struct strip_this_argument > +{ + typedef vector type; +}; + +template +typename strip_this_argument< + decltype(deduce_signature(&F::operator())) +>::type deduce_signature(F const&) +{ + return typename strip_this_argument< + decltype(deduce_signature(&F::operator()))>::type(); +} + +# else // LUABIND_CPP0x + namespace mpl = boost::mpl; template @@ -58,6 +131,8 @@ deduce_signature(R(T::*)() const, Wrapped*) (3, (1, LUABIND_MAX_ARITY, )) # include BOOST_PP_ITERATE() +# endif // LUABIND_CPP0x + }} // namespace luabind::detail # endif // LUABIND_DEDUCE_SIGNATURE_080911_HPP diff --git a/luabind/detail/format_signature.hpp b/luabind/detail/format_signature.hpp index b447bc9..c159dd4 100644 --- a/luabind/detail/format_signature.hpp +++ b/luabind/detail/format_signature.hpp @@ -114,6 +114,8 @@ struct type_to_string > } }; +# ifndef LUABIND_CPP0x + template void format_signature_aux(lua_State*, bool, End, End) {} @@ -149,6 +151,37 @@ void format_signature(lua_State* L, char const* function, Signature) lua_concat(L, static_cast(mpl::size()) * 2 + 2); } +# else // LUABIND_CPP0x + +inline void format_signature_aux(lua_State*, vector<>, bool) +{} + +template +void format_signature_aux(lua_State* L, vector, bool first = true) +{ + if (!first) + lua_pushstring(L, ","); + type_to_string::get(L); + format_signature_aux(L, vector(), false); +} + +template +void format_signature(lua_State* L, char const* function, vector) +{ + type_to_string::get(L); + + lua_pushstring(L, " "); + lua_pushstring(L, function); + + lua_pushstring(L, "("); + format_signature_aux(L, vector()); + lua_pushstring(L, ")"); + + lua_concat(L, (sizeof...(Args) + 1) * 2 + 2); +} + +# endif // LUABIND_CPP0x + }} // namespace luabind::detail #endif // LUABIND_FORMAT_SIGNATURE_081014_HPP diff --git a/luabind/detail/policy.hpp b/luabind/detail/policy.hpp index 8a040d4..77de640 100644 --- a/luabind/detail/policy.hpp +++ b/luabind/detail/policy.hpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include diff --git a/luabind/detail/signature_match.hpp b/luabind/detail/signature_match.hpp index d76ed66..ae64429 100644 --- a/luabind/detail/signature_match.hpp +++ b/luabind/detail/signature_match.hpp @@ -26,14 +26,15 @@ #include #include -#include -#include -#include -#include - -#include -#include -#include +#ifndef LUABIND_CPP0x +# include +# include +# include +# include +# include +# include +# include +#endif namespace luabind { @@ -43,6 +44,16 @@ namespace luabind class argument; } +# ifdef LUABIND_CPP0x + + template + struct constructor + { + typedef vector signature; + }; + +# else + template struct constructor { @@ -55,6 +66,8 @@ namespace luabind signature0, detail::null_type>::type signature; }; +# endif // LUABIND_CPP0x + } #endif // LUABIND_SIGNATURE_MATCH_HPP_INCLUDED diff --git a/luabind/make_function.hpp b/luabind/make_function.hpp index 8dd71df..77cd5ae 100644 --- a/luabind/make_function.hpp +++ b/luabind/make_function.hpp @@ -7,6 +7,7 @@ # include # include +# include # include # include # include @@ -102,9 +103,11 @@ namespace detail template object make_function(lua_State* L, F f, Signature, Policies) { + typedef typename detail::as_vector::type signature; + return detail::make_function_aux( L - , new detail::function_object_impl( + , new detail::function_object_impl( f, Policies() ) ); diff --git a/luabind/object.hpp b/luabind/object.hpp index a370514..aa54dcf 100644 --- a/luabind/object.hpp +++ b/luabind/object.hpp @@ -42,7 +42,9 @@ #include // iterator +#ifndef LUABIND_CPP0x #include +#endif #include namespace luabind { @@ -275,6 +277,19 @@ LUABIND_BINARY_OP_DEF(<, lua_lessthan) public: ~object_interface() {} +# ifdef LUABIND_CPP0x + + template + call_proxy< + Derived, std::tuple + > operator()(Args const& ...args) + { + typedef std::tuple arguments; + return call_proxy(derived(), arguments(&args...)); + } + +# else + call_proxy > operator()(); template @@ -310,6 +325,8 @@ LUABIND_BINARY_OP_DEF(<, lua_lessthan) (3, LUABIND_MAX_ARITY, )) #include BOOST_PP_ITERATE() +# endif // LUABIND_CPP0x + operator safe_bool_type*() const { lua_State* L = value_wrapper_traits::interpreter(derived()); @@ -1064,6 +1081,37 @@ namespace detail template struct push_args_from_tuple { +# ifdef LUABIND_CPP0x + + template + static void push_args( + lua_State* L, Args const& args, Policies const& policies, N, E) + { + convert_to_lua_p(L, *std::get(args), policies); + push_args( + L, args, policies, std::integral_constant(), E()); + } + + template + static void push_args(lua_State* L, Args const&, Policies const&, E, E) + {} + + template + static void apply( + lua_State* L, std::tuple const& args + , Policies const policies = Policies()) + { + push_args( + L + , args + , policies + , std::integral_constant() + , std::integral_constant() + ); + } + +# else // LUABIND_CPP0x + template inline static void apply(lua_State* L, const boost::tuples::cons& x, const Policies& p) { @@ -1082,6 +1130,8 @@ namespace detail inline static void apply(lua_State*, const boost::tuples::null_type&, const Policies&) {} inline static void apply(lua_State*, const boost::tuples::null_type&) {} + +# endif // LUABIND_CPP0x }; } // namespace detail @@ -1137,7 +1187,11 @@ namespace adl detail::push_args_from_tuple<1>::apply(interpreter, arguments, Policies()); +# ifdef LUABIND_CPP0x + if (detail::pcall(interpreter, std::tuple_size::value, 1)) +# else if (detail::pcall(interpreter, boost::tuples::length::value, 1)) +# endif { #ifndef LUABIND_NO_EXCEPTIONS throw luabind::error(interpreter); @@ -1159,6 +1213,8 @@ namespace adl Arguments arguments; }; +# ifndef LUABIND_CPP0x + template call_proxy > object_interface::operator()() @@ -1169,6 +1225,8 @@ namespace adl ); } +# endif + // Simple value_wrapper adaptor with the sole purpose of helping with // overload resolution. Use this as a function parameter type instead // of "object" or "argument" to restrict the parameter to Lua tables. diff --git a/luabind/operator.hpp b/luabind/operator.hpp index aeb651c..f18f774 100755 --- a/luabind/operator.hpp +++ b/luabind/operator.hpp @@ -26,8 +26,10 @@ #include #include #include +#ifndef LUABIND_CPP0x #include #include +#endif #include #include #include @@ -65,24 +67,68 @@ namespace luabind { namespace detail { namespace luabind { namespace operators { +# ifdef LUABIND_CPP0x + +template +struct call_operator + : detail::operator_ +{ + call_operator(int) + {} + + template + struct apply + { + static void execute( + lua_State* L + , typename detail::unwrap_parameter_type::type self + , detail::unwrap_parameter_type::type args... + ) + { + using namespace detail; + operator_result( + L + , (self(args...), detail::operator_void_return()) + , (Policies*)0 + ); + } + }; + + static char const* name() { return "__call"; } +}; + +# else // LUABIND_CPP_0x #define BOOST_PP_ITERATION_PARAMS_1 (3, \ (0, LUABIND_MAX_ARITY, )) #include BOOST_PP_ITERATE() +# endif // LUABIND_CPP_0x }} // namespace luabind::operators -#include +#ifndef LUABIND_CPP0x +# include +#endif namespace luabind { template struct self_base { +# ifdef LUABIND_CPP0x + + template + operators::call_operator operator()(Args const&...) const + { + return 0; + } + +# else // LUABIND_CPP0x + operators::call_operator0 operator()() const { return 0; } - + #define BOOST_PP_LOCAL_MACRO(n) \ template \ BOOST_PP_CAT(operators::call_operator, n)< \ @@ -99,6 +145,8 @@ namespace luabind { #define BOOST_PP_LOCAL_LIMITS (1, LUABIND_MAX_ARITY) #include BOOST_PP_LOCAL_ITERATE() +# endif // LUABIND_CPP0x + }; struct self_type : self_base diff --git a/luabind/tag_function.hpp b/luabind/tag_function.hpp index 51fe97b..4a32db8 100644 --- a/luabind/tag_function.hpp +++ b/luabind/tag_function.hpp @@ -7,15 +7,17 @@ # ifndef LUABIND_TAG_FUNCTION_081129_HPP # define LUABIND_TAG_FUNCTION_081129_HPP -# if LUABIND_MAX_ARITY <= 8 -# include -# else -# include +# ifndef LUABIND_CPP0x +# if LUABIND_MAX_ARITY <= 8 +# include +# else +# include +# endif +# include +# include +# include +# include # endif -# include -# include -# include -# include namespace luabind { @@ -38,6 +40,28 @@ namespace detail return Signature(); } + template + struct signature_from_function; + +# ifdef LUABIND_CPP0x + + template + int invoke( + lua_State* L, function_object const& self, invoke_context& ctx + , tagged_function, F> const& tagged + , vector, Policies const& policies) + { + return invoke(L, self, ctx, tagged.f, vector(), policies); + } + + template + struct signature_from_function + { + typedef vector type; + }; + +# else // LUABIND_CPP0x + template int invoke( lua_State* L, function_object const& self, invoke_context& ctx @@ -47,13 +71,12 @@ namespace detail return invoke(L, self, ctx, tagged.f, Signature(), policies); } - template - struct signature_from_function; - -# define BOOST_PP_ITERATION_PARAMS_1 \ +# define BOOST_PP_ITERATION_PARAMS_1 \ (3, (0, LUABIND_MAX_ARITY, )) # include BOOST_PP_ITERATE() +# endif // LUABIND_CPP0x + } // namespace detail template diff --git a/luabind/vector.hpp b/luabind/vector.hpp new file mode 100644 index 0000000..69a5796 --- /dev/null +++ b/luabind/vector.hpp @@ -0,0 +1,125 @@ +// Copyright Daniel Wallin 2010. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_VECTOR_100629_HPP +# define LUABIND_VECTOR_100629_HPP + +# ifdef LUABIND_CPP0x + +# include +# include +# include +# include + +namespace luabind { + +// This is used to specify function signatures, both in the user interface and +// in the implementation. In the C++03 version this used to be any MPL forward +// sequence. For backward compatibility reasons we provide a conversion layer +// from an MPL sequence. +template +struct vector +{}; + +namespace detail +{ + + + template + struct vector_iterator; + + template + struct vector_iterator + { + typedef Head type; + typedef vector_iterator next; + }; + + template <> + struct vector_iterator<> + {}; + +} // namespace detail + +} // namespace luabind + +namespace boost { namespace mpl +{ + + // MPL sequence adaption layer to ease the transition to C++0x. + + template + struct begin > + { + typedef luabind::detail::vector_iterator type; + }; + + template + struct end > + { + typedef luabind::detail::vector_iterator<> type; + }; + + template + struct size > + : long_ + {}; + + template + struct front > + { + typedef Head type; + }; + + template + struct deref > + { + typedef Head type; + }; + +}} // namespace boost::mpl + +# endif // LUABIND_CPP0x + +namespace luabind { namespace detail +{ + +# ifdef LUABIND_CPP0x + + struct append_vector + { + template + struct apply; + + template + struct apply, T> + { + typedef vector type; + }; + }; + + template + struct as_vector + : boost::mpl::fold, append_vector> + {}; + + template + struct as_vector > + { + typedef vector type; + }; + +# else // LUABIND_CPP0x + + template + struct as_vector + { + typedef Sequence type; + }; + +# endif + +}} // namespace luabind::detail + +#endif // LUABIND_VECTOR_100629_HPP diff --git a/luabind/wrapper_base.hpp b/luabind/wrapper_base.hpp index d54c668..a74416b 100755 --- a/luabind/wrapper_base.hpp +++ b/luabind/wrapper_base.hpp @@ -30,8 +30,10 @@ #include #include -#include -#include +#ifndef LUABIND_CPP0x +# include +# include +#endif #include @@ -60,16 +62,58 @@ namespace luabind friend struct detail::wrap_access; wrap_base() {} +# ifdef LUABIND_CPP0x + + template + typename detail::make_member_proxy::type call( + char const* name, Args const&... args) const + { + lua_State* L = m_self.state(); + m_self.get(L); + assert(!lua_isnil(L, -1)); + detail::do_call_member_selection(L, name); + + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + throw std::runtime_error("Attempt to call nonexistent function"); + } + + // push the self reference as the first parameter + m_self.get(L); + + typedef typename detail::make_member_proxy::type + proxy_type; + return proxy_type(L, std::tuple(&args...)); + } + +# else // LUABIND_CPP0x + #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, , 1)) #include BOOST_PP_ITERATE() +# endif // LUABIND_CPP0x + private: wrapped_self_t m_self; }; -#define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, , 2)) +# ifdef LUABIND_CPP0x + + template + typename detail::make_member_proxy::type call_member( + wrap_base const* self, char const* name, Args const&... args) + { + return self->call(name, args...); + } + +# else // LUABIND_CPP0x + +# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, , 2)) #include BOOST_PP_ITERATE() +# endif // LUABIND_CPP0x + namespace detail { struct wrap_access diff --git a/test/Jamfile b/test/Jamfile index 804da56..315bac8 100755 --- a/test/Jamfile +++ b/test/Jamfile @@ -45,6 +45,7 @@ SOURCES = test_super_leak.cpp test_set_instance_value.cpp test_unsigned_int.cpp + test_def_function_object.cpp ; obj main : main.cpp : ..//luabind : : ..//luabind ; -- 2.11.4.GIT