diff --git a/single/sol/sol.hpp b/single/sol/sol.hpp index 4ae84603..ec1b0ba6 100644 --- a/single/sol/sol.hpp +++ b/single/sol/sol.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2017-02-16 04:42:52.309916 UTC -// This header was generated with sol v2.15.8 (revision 4aee6d3) +// Generated 2017-02-17 10:46:09.695757 UTC +// This header was generated with sol v2.15.8 (revision 37420dc) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -8715,6 +8715,10 @@ namespace sol { // end of sol/resolve.hpp namespace sol { + namespace function_detail { + template + struct class_indicator {}; + } namespace stack { template struct pusher> { @@ -8770,12 +8774,19 @@ namespace sol { select_convertible(types(), L, std::forward(fx), std::forward(args)...); } - template + template >> = meta::enabler> static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { typedef meta::boolean>::value || std::is_pointer::value> is_reference; select_reference_member_variable(is_reference(), L, std::forward(fx), std::forward(obj), std::forward(args)...); } + template + static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator) { + lua_CFunction freefunc = &function_detail::upvalue_this_member_variable::call; + int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } + template static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) { typedef typename meta::bind_traits>::object_type C; @@ -8808,12 +8819,19 @@ namespace sol { select_member_variable(std::is_member_object_pointer>(), L, std::forward(fx), std::forward(args)...); } - template + template >> = meta::enabler> static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { typedef meta::boolean>::value || std::is_pointer::value> is_reference; select_reference_member_function(is_reference(), L, std::forward(fx), std::forward(obj), std::forward(args)...); } + template + static void select_member_function(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator) { + lua_CFunction freefunc = &function_detail::upvalue_this_member_function::call; + int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } + template static void select_member_function(std::true_type, lua_State* L, Fx&& fx) { typedef typename meta::bind_traits>::object_type C; @@ -8886,9 +8904,9 @@ namespace sol { template struct pusher::value>> { - template - static int push(lua_State* L, F&& f) { - return pusher>{}.push(L, std::forward(f)); + template + static int push(lua_State* L, F&& f, Args&&... args) { + return pusher>{}.push(L, std::forward(f), std::forward(args)...); } }; @@ -10807,6 +10825,26 @@ namespace sol { hint->second = std::move(o); } + template + void add_member_function(std::true_type, lua_State* L, N&& n, F&& f) { + object o = make_object(L, std::forward(f), function_detail::class_indicator()); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template + void add_member_function(std::false_type, lua_State* L, N&& n, F&& f) { + object o = make_object(L, std::forward(f)); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + template >> = meta::enabler> void add_function(lua_State* L, N&& n, F&& f) { insert(std::forward(n), make_object(L, as_function_reference(std::forward(f)))); @@ -10814,12 +10852,7 @@ namespace sol { template >> = meta::enabler> void add_function(lua_State* L, N&& n, F&& f) { - object o = make_object(L, std::forward(f)); - if (std::is_same, call_construction>::value) { - callconstructfunc = std::move(o); - return; - } - insert(std::forward(n), std::move(o)); + add_member_function(std::is_member_pointer>(), L, std::forward(n), std::forward(f)); } template >> = meta::enabler> diff --git a/sol/function_types.hpp b/sol/function_types.hpp index 4dde4682..f08c7f8f 100644 --- a/sol/function_types.hpp +++ b/sol/function_types.hpp @@ -1,342 +1,360 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_FUNCTION_TYPES_HPP -#define SOL_FUNCTION_TYPES_HPP - -#include "function_types_core.hpp" -#include "function_types_templated.hpp" -#include "function_types_stateless.hpp" -#include "function_types_stateful.hpp" -#include "function_types_overloaded.hpp" -#include "resolve.hpp" -#include "call.hpp" - -namespace sol { - namespace stack { - template - struct pusher> { - template - static void select_convertible(std::false_type, types, lua_State* L, Fx&& fx, Args&&... args) { - typedef std::remove_pointer_t> clean_fx; - typedef function_detail::functor_function F; - set_fx(L, std::forward(fx), std::forward(args)...); - } - - template - static void select_convertible(std::true_type, types, lua_State* L, Fx&& fx, Args&&... args) { - using fx_ptr_t = R(*)(A...); - fx_ptr_t fxptr = detail::unwrap(std::forward(fx)); - select_function(std::true_type(), L, fxptr, std::forward(args)...); - } - - template - static void select_convertible(types t, lua_State* L, Fx&& fx, Args&&... args) { - typedef std::decay_t> raw_fx_t; - typedef R(*fx_ptr_t)(A...); - typedef std::is_convertible is_convertible; - select_convertible(is_convertible(), t, L, std::forward(fx), std::forward(args)...); - } - - template - static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) { - typedef meta::function_signature_t> Sig; - select_convertible(types(), L, std::forward(fx), std::forward(args)...); - } - - template - static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef std::remove_pointer_t> clean_fx; - typedef function_detail::member_variable, clean_fx> F; - set_fx(L, std::forward(fx), std::forward(obj), std::forward(args)...); - } - - template - static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef std::decay_t dFx; - dFx memfxptr(std::forward(fx)); - auto userptr = detail::ptr(std::forward(obj), std::forward(args)...); - lua_CFunction freefunc = &function_detail::upvalue_member_variable, meta::unqualified_t>::call; - - int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); - upvalues += stack::push(L, lightuserdata_value(static_cast(userptr))); - stack::push(L, c_closure(freefunc, upvalues)); - } - - template - static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { - select_convertible(types(), L, std::forward(fx), std::forward(args)...); - } - - template - static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef meta::boolean>::value || std::is_pointer::value> is_reference; - select_reference_member_variable(is_reference(), L, std::forward(fx), std::forward(obj), std::forward(args)...); - } - - template - static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) { - typedef typename meta::bind_traits>::object_type C; - lua_CFunction freefunc = &function_detail::upvalue_this_member_variable::call; - int upvalues = stack::stack_detail::push_as_upvalues(L, fx); - stack::push(L, c_closure(freefunc, upvalues)); - } - - template - static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef std::decay_t clean_fx; - typedef function_detail::member_function, clean_fx> F; - set_fx(L, std::forward(fx), std::forward(obj), std::forward(args)...); - } - - template - static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef std::decay_t dFx; - dFx memfxptr(std::forward(fx)); - auto userptr = detail::ptr(std::forward(obj), std::forward(args)...); - lua_CFunction freefunc = &function_detail::upvalue_member_function, meta::unqualified_t>::call; - - int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); - upvalues += stack::push(L, lightuserdata_value(static_cast(userptr))); - stack::push(L, c_closure(freefunc, upvalues)); - } - - template - static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { - select_member_variable(std::is_member_object_pointer>(), L, std::forward(fx), std::forward(args)...); - } - - template - static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef meta::boolean>::value || std::is_pointer::value> is_reference; - select_reference_member_function(is_reference(), L, std::forward(fx), std::forward(obj), std::forward(args)...); - } - - template - static void select_member_function(std::true_type, lua_State* L, Fx&& fx) { - typedef typename meta::bind_traits>::object_type C; - lua_CFunction freefunc = &function_detail::upvalue_this_member_function::call; - int upvalues = stack::stack_detail::push_as_upvalues(L, fx); - stack::push(L, c_closure(freefunc, upvalues)); - } - - template - static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { - select_member_function(std::is_member_function_pointer>(), L, std::forward(fx), std::forward(args)...); - } - - template - static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) { - std::decay_t target(std::forward(fx), std::forward(args)...); - lua_CFunction freefunc = &function_detail::upvalue_free_function::call; - - int upvalues = stack::stack_detail::push_as_upvalues(L, target); - stack::push(L, c_closure(freefunc, upvalues)); - } - - static void select_function(std::true_type, lua_State* L, lua_CFunction f) { - stack::push(L, f); - } - - template - static void select(lua_State* L, Fx&& fx, Args&&... args) { - select_function(std::is_function>(), L, std::forward(fx), std::forward(args)...); - } - - template - static void set_fx(lua_State* L, Args&&... args) { - lua_CFunction freefunc = function_detail::call>; - - stack::push>(L, std::forward(args)...); - stack::push(L, c_closure(freefunc, 1)); - } - - template - static int push(lua_State* L, Args&&... args) { - // Set will always place one thing (function) on the stack - select(L, std::forward(args)...); - return 1; - } - }; - - template - struct pusher> { - template - static int push_func(std::index_sequence, lua_State* L, FP&& fp) { - return stack::push(L, detail::forward_get(fp.arguments)...); - } - - static int push(lua_State* L, const function_arguments& fp) { - return push_func(std::make_index_sequence(), L, fp); - } - - static int push(lua_State* L, function_arguments&& fp) { - return push_func(std::make_index_sequence(), L, std::move(fp)); - } - }; - - template - struct pusher> { - static int push(lua_State* L, std::function fx) { - return pusher>{}.push(L, std::move(fx)); - } - }; - - template - struct pusher::value>> { - template - static int push(lua_State* L, F&& f) { - return pusher>{}.push(L, std::forward(f)); - } - }; - - template - struct pusher, meta::neg>, meta::neg>>>::value>> { - template - static int push(lua_State* L, F&& f) { - return pusher>{}.push(L, std::forward(f)); - } - }; - - template - struct pusher> { - static int push(lua_State* L, overload_set&& set) { - typedef function_detail::overloaded_function F; - pusher>{}.set_fx(L, std::move(set.functions)); - return 1; - } - - static int push(lua_State* L, const overload_set& set) { - typedef function_detail::overloaded_function F; - pusher>{}.set_fx(L, set.functions); - return 1; - } - }; - - template - struct pusher> { - static int push(lua_State* L, protect_t&& pw) { - lua_CFunction cf = call_detail::call_user>; - int closures = stack::push>>(L, std::move(pw.value)); - return stack::push(L, c_closure(cf, closures)); - } - - static int push(lua_State* L, const protect_t& pw) { - lua_CFunction cf = call_detail::call_user>; - int closures = stack::push>>(L, pw.value); - return stack::push(L, c_closure(cf, closures)); - } - }; - - template - struct pusher, std::enable_if_t::value && !std::is_void::value>> { - static int push(lua_State* L, property_wrapper&& pw) { - return stack::push(L, sol::overload(std::move(pw.read), std::move(pw.write))); - } - static int push(lua_State* L, const property_wrapper& pw) { - return stack::push(L, sol::overload(pw.read, pw.write)); - } - }; - - template - struct pusher> { - static int push(lua_State* L, property_wrapper&& pw) { - return stack::push(L, std::move(pw.read)); - } - static int push(lua_State* L, const property_wrapper& pw) { - return stack::push(L, pw.read); - } - }; - - template - struct pusher> { - static int push(lua_State* L, property_wrapper&& pw) { - return stack::push(L, std::move(pw.write)); - } - static int push(lua_State* L, const property_wrapper& pw) { - return stack::push(L, pw.write); - } - }; - - template - struct pusher> { - static int push(lua_State* L, var_wrapper&& vw) { - return stack::push(L, std::move(vw.value)); - } - static int push(lua_State* L, const var_wrapper& vw) { - return stack::push(L, vw.value); - } - }; - - template - struct pusher> { - static int push(lua_State* L, const factory_wrapper& fw) { - typedef function_detail::overloaded_function F; - pusher>{}.set_fx(L, fw.functions); - return 1; - } - - static int push(lua_State* L, factory_wrapper&& fw) { - typedef function_detail::overloaded_function F; - pusher>{}.set_fx(L, std::move(fw.functions)); - return 1; - } - }; - - template - struct pusher>> { - static int push(lua_State* L, detail::tagged>) { - lua_CFunction cf = call_detail::construct; - return stack::push(L, cf); - } - }; - - template - struct pusher>> { - template - static int push(lua_State* L, C&& c) { - lua_CFunction cf = call_detail::call_user>; - int closures = stack::push>>(L, std::forward(c)); - return stack::push(L, c_closure(cf, closures)); - } - }; - - template - struct pusher>> { - static int push(lua_State* L, destructor_wrapper) { - lua_CFunction cf = detail::usertype_alloc_destroy; - return stack::push(L, cf); - } - }; - - template - struct pusher>> { - static int push(lua_State* L, destructor_wrapper c) { - lua_CFunction cf = call_detail::call_user>; - int closures = stack::push>(L, std::move(c)); - return stack::push(L, c_closure(cf, closures)); - } - }; - - } // stack -} // sol - -#endif // SOL_FUNCTION_TYPES_HPP +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_FUNCTION_TYPES_HPP +#define SOL_FUNCTION_TYPES_HPP + +#include "function_types_core.hpp" +#include "function_types_templated.hpp" +#include "function_types_stateless.hpp" +#include "function_types_stateful.hpp" +#include "function_types_overloaded.hpp" +#include "resolve.hpp" +#include "call.hpp" + +namespace sol { + namespace function_detail { + template + struct class_indicator {}; + } + namespace stack { + template + struct pusher> { + template + static void select_convertible(std::false_type, types, lua_State* L, Fx&& fx, Args&&... args) { + typedef std::remove_pointer_t> clean_fx; + typedef function_detail::functor_function F; + set_fx(L, std::forward(fx), std::forward(args)...); + } + + template + static void select_convertible(std::true_type, types, lua_State* L, Fx&& fx, Args&&... args) { + using fx_ptr_t = R(*)(A...); + fx_ptr_t fxptr = detail::unwrap(std::forward(fx)); + select_function(std::true_type(), L, fxptr, std::forward(args)...); + } + + template + static void select_convertible(types t, lua_State* L, Fx&& fx, Args&&... args) { + typedef std::decay_t> raw_fx_t; + typedef R(*fx_ptr_t)(A...); + typedef std::is_convertible is_convertible; + select_convertible(is_convertible(), t, L, std::forward(fx), std::forward(args)...); + } + + template + static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) { + typedef meta::function_signature_t> Sig; + select_convertible(types(), L, std::forward(fx), std::forward(args)...); + } + + template + static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::remove_pointer_t> clean_fx; + typedef function_detail::member_variable, clean_fx> F; + set_fx(L, std::forward(fx), std::forward(obj), std::forward(args)...); + } + + template + static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::decay_t dFx; + dFx memfxptr(std::forward(fx)); + auto userptr = detail::ptr(std::forward(obj), std::forward(args)...); + lua_CFunction freefunc = &function_detail::upvalue_member_variable, meta::unqualified_t>::call; + + int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); + upvalues += stack::push(L, lightuserdata_value(static_cast(userptr))); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { + select_convertible(types(), L, std::forward(fx), std::forward(args)...); + } + + template >> = meta::enabler> + static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef meta::boolean>::value || std::is_pointer::value> is_reference; + select_reference_member_variable(is_reference(), L, std::forward(fx), std::forward(obj), std::forward(args)...); + } + + template + static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator) { + lua_CFunction freefunc = &function_detail::upvalue_this_member_variable::call; + int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) { + typedef typename meta::bind_traits>::object_type C; + lua_CFunction freefunc = &function_detail::upvalue_this_member_variable::call; + int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::decay_t clean_fx; + typedef function_detail::member_function, clean_fx> F; + set_fx(L, std::forward(fx), std::forward(obj), std::forward(args)...); + } + + template + static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::decay_t dFx; + dFx memfxptr(std::forward(fx)); + auto userptr = detail::ptr(std::forward(obj), std::forward(args)...); + lua_CFunction freefunc = &function_detail::upvalue_member_function, meta::unqualified_t>::call; + + int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); + upvalues += stack::push(L, lightuserdata_value(static_cast(userptr))); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { + select_member_variable(std::is_member_object_pointer>(), L, std::forward(fx), std::forward(args)...); + } + + template >> = meta::enabler> + static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef meta::boolean>::value || std::is_pointer::value> is_reference; + select_reference_member_function(is_reference(), L, std::forward(fx), std::forward(obj), std::forward(args)...); + } + + template + static void select_member_function(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator) { + lua_CFunction freefunc = &function_detail::upvalue_this_member_function::call; + int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_member_function(std::true_type, lua_State* L, Fx&& fx) { + typedef typename meta::bind_traits>::object_type C; + lua_CFunction freefunc = &function_detail::upvalue_this_member_function::call; + int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { + select_member_function(std::is_member_function_pointer>(), L, std::forward(fx), std::forward(args)...); + } + + template + static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) { + std::decay_t target(std::forward(fx), std::forward(args)...); + lua_CFunction freefunc = &function_detail::upvalue_free_function::call; + + int upvalues = stack::stack_detail::push_as_upvalues(L, target); + stack::push(L, c_closure(freefunc, upvalues)); + } + + static void select_function(std::true_type, lua_State* L, lua_CFunction f) { + stack::push(L, f); + } + + template + static void select(lua_State* L, Fx&& fx, Args&&... args) { + select_function(std::is_function>(), L, std::forward(fx), std::forward(args)...); + } + + template + static void set_fx(lua_State* L, Args&&... args) { + lua_CFunction freefunc = function_detail::call>; + + stack::push>(L, std::forward(args)...); + stack::push(L, c_closure(freefunc, 1)); + } + + template + static int push(lua_State* L, Args&&... args) { + // Set will always place one thing (function) on the stack + select(L, std::forward(args)...); + return 1; + } + }; + + template + struct pusher> { + template + static int push_func(std::index_sequence, lua_State* L, FP&& fp) { + return stack::push(L, detail::forward_get(fp.arguments)...); + } + + static int push(lua_State* L, const function_arguments& fp) { + return push_func(std::make_index_sequence(), L, fp); + } + + static int push(lua_State* L, function_arguments&& fp) { + return push_func(std::make_index_sequence(), L, std::move(fp)); + } + }; + + template + struct pusher> { + static int push(lua_State* L, std::function fx) { + return pusher>{}.push(L, std::move(fx)); + } + }; + + template + struct pusher::value>> { + template + static int push(lua_State* L, F&& f, Args&&... args) { + return pusher>{}.push(L, std::forward(f), std::forward(args)...); + } + }; + + template + struct pusher, meta::neg>, meta::neg>>>::value>> { + template + static int push(lua_State* L, F&& f) { + return pusher>{}.push(L, std::forward(f)); + } + }; + + template + struct pusher> { + static int push(lua_State* L, overload_set&& set) { + typedef function_detail::overloaded_function F; + pusher>{}.set_fx(L, std::move(set.functions)); + return 1; + } + + static int push(lua_State* L, const overload_set& set) { + typedef function_detail::overloaded_function F; + pusher>{}.set_fx(L, set.functions); + return 1; + } + }; + + template + struct pusher> { + static int push(lua_State* L, protect_t&& pw) { + lua_CFunction cf = call_detail::call_user>; + int closures = stack::push>>(L, std::move(pw.value)); + return stack::push(L, c_closure(cf, closures)); + } + + static int push(lua_State* L, const protect_t& pw) { + lua_CFunction cf = call_detail::call_user>; + int closures = stack::push>>(L, pw.value); + return stack::push(L, c_closure(cf, closures)); + } + }; + + template + struct pusher, std::enable_if_t::value && !std::is_void::value>> { + static int push(lua_State* L, property_wrapper&& pw) { + return stack::push(L, sol::overload(std::move(pw.read), std::move(pw.write))); + } + static int push(lua_State* L, const property_wrapper& pw) { + return stack::push(L, sol::overload(pw.read, pw.write)); + } + }; + + template + struct pusher> { + static int push(lua_State* L, property_wrapper&& pw) { + return stack::push(L, std::move(pw.read)); + } + static int push(lua_State* L, const property_wrapper& pw) { + return stack::push(L, pw.read); + } + }; + + template + struct pusher> { + static int push(lua_State* L, property_wrapper&& pw) { + return stack::push(L, std::move(pw.write)); + } + static int push(lua_State* L, const property_wrapper& pw) { + return stack::push(L, pw.write); + } + }; + + template + struct pusher> { + static int push(lua_State* L, var_wrapper&& vw) { + return stack::push(L, std::move(vw.value)); + } + static int push(lua_State* L, const var_wrapper& vw) { + return stack::push(L, vw.value); + } + }; + + template + struct pusher> { + static int push(lua_State* L, const factory_wrapper& fw) { + typedef function_detail::overloaded_function F; + pusher>{}.set_fx(L, fw.functions); + return 1; + } + + static int push(lua_State* L, factory_wrapper&& fw) { + typedef function_detail::overloaded_function F; + pusher>{}.set_fx(L, std::move(fw.functions)); + return 1; + } + }; + + template + struct pusher>> { + static int push(lua_State* L, detail::tagged>) { + lua_CFunction cf = call_detail::construct; + return stack::push(L, cf); + } + }; + + template + struct pusher>> { + template + static int push(lua_State* L, C&& c) { + lua_CFunction cf = call_detail::call_user>; + int closures = stack::push>>(L, std::forward(c)); + return stack::push(L, c_closure(cf, closures)); + } + }; + + template + struct pusher>> { + static int push(lua_State* L, destructor_wrapper) { + lua_CFunction cf = detail::usertype_alloc_destroy; + return stack::push(L, cf); + } + }; + + template + struct pusher>> { + static int push(lua_State* L, destructor_wrapper c) { + lua_CFunction cf = call_detail::call_user>; + int closures = stack::push>(L, std::move(c)); + return stack::push(L, c_closure(cf, closures)); + } + }; + + } // stack +} // sol + +#endif // SOL_FUNCTION_TYPES_HPP diff --git a/sol/simple_usertype_metatable.hpp b/sol/simple_usertype_metatable.hpp index 7570a329..76205752 100644 --- a/sol/simple_usertype_metatable.hpp +++ b/sol/simple_usertype_metatable.hpp @@ -208,6 +208,26 @@ namespace sol { hint->second = std::move(o); } + template + void add_member_function(std::true_type, lua_State* L, N&& n, F&& f) { + object o = make_object(L, std::forward(f), function_detail::class_indicator()); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template + void add_member_function(std::false_type, lua_State* L, N&& n, F&& f) { + object o = make_object(L, std::forward(f)); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + template >> = meta::enabler> void add_function(lua_State* L, N&& n, F&& f) { insert(std::forward(n), make_object(L, as_function_reference(std::forward(f)))); @@ -215,12 +235,7 @@ namespace sol { template >> = meta::enabler> void add_function(lua_State* L, N&& n, F&& f) { - object o = make_object(L, std::forward(f)); - if (std::is_same, call_construction>::value) { - callconstructfunc = std::move(o); - return; - } - insert(std::forward(n), std::move(o)); + add_member_function(std::is_member_pointer>(), L, std::forward(n), std::forward(f)); } template >> = meta::enabler> diff --git a/sol/traits.hpp b/sol/traits.hpp index d1d8fc63..1ed95a16 100644 --- a/sol/traits.hpp +++ b/sol/traits.hpp @@ -1,428 +1,428 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_TRAITS_HPP -#define SOL_TRAITS_HPP - -#include "tuple.hpp" -#include "bind_traits.hpp" -#include -#include -#include - -namespace sol { - template - using index_value = std::integral_constant; - - namespace meta { - template - struct identity { typedef T type; }; - - template - using identity_t = typename identity::type; - - template - struct is_tuple : std::false_type { }; - - template - struct is_tuple> : std::true_type { }; - - template - struct is_builtin_type : std::integral_constant::value || std::is_pointer::value || std::is_array::value> {}; - - template - struct unwrapped { - typedef T type; - }; - - template - struct unwrapped> { - typedef T type; - }; - - template - using unwrapped_t = typename unwrapped::type; - - template - struct unwrap_unqualified : unwrapped> {}; - - template - using unwrap_unqualified_t = typename unwrap_unqualified::type; - - template - struct remove_member_pointer; - - template - struct remove_member_pointer { - typedef R type; - }; - - template - struct remove_member_pointer { - typedef R type; - }; - - template - using remove_member_pointer_t = remove_member_pointer; - - template class Templ, typename T> - struct is_specialization_of : std::false_type { }; - template class Templ> - struct is_specialization_of> : std::true_type { }; - - template - struct all_same : std::true_type { }; - - template - struct all_same : std::integral_constant ::value && all_same::value> { }; - - template - struct any_same : std::false_type { }; - - template - struct any_same : std::integral_constant ::value || any_same::value> { }; - - template - using invoke_t = typename T::type; - - template - using boolean = std::integral_constant; - - template - using neg = boolean; - - template - using condition = std::conditional_t; - - template - struct all : boolean {}; - - template - struct all : condition, boolean> {}; - - template - struct any : boolean {}; - - template - struct any : condition, any> {}; - - enum class enable_t { - _ - }; - - constexpr const auto enabler = enable_t::_; - - template - using disable_if_t = std::enable_if_t; - - template - using enable = std::enable_if_t::value, enable_t>; - - template - using disable = std::enable_if_t>::value, enable_t>; - - template - using disable_any = std::enable_if_t>::value, enable_t>; - - template - struct find_in_pack_v : boolean { }; - - template - struct find_in_pack_v : any, find_in_pack_v> { }; - - namespace meta_detail { - template - struct index_in_pack : std::integral_constant { }; - - template - struct index_in_pack : std::conditional_t::value, std::integral_constant, index_in_pack> { }; - } - - template - struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> { }; - - template - struct index_in : meta_detail::index_in_pack<0, T, List> { }; - - template - struct index_in> : meta_detail::index_in_pack<0, T, Args...> { }; - - template - struct at_in_pack {}; - - template - using at_in_pack_t = typename at_in_pack::type; - - template - struct at_in_pack : std::conditional> {}; - - template - struct at_in_pack<0, Arg, Args...> { typedef Arg type; }; - - namespace meta_detail { - template class Pred, typename... Ts> - struct count_for_pack : std::integral_constant {}; - template class Pred, typename T, typename... Ts> - struct count_for_pack : std::conditional_t < sizeof...(Ts) == 0 || Limit < 2, - std::integral_constant(Limit != 0 && Pred::value)>, - count_for_pack(Pred::value), Pred, Ts...> - > { }; - template class Pred, typename... Ts> - struct count_2_for_pack : std::integral_constant {}; - template class Pred, typename T, typename U, typename... Ts> - struct count_2_for_pack : std::conditional_t(Pred::value)>, - count_2_for_pack(Pred::value), Pred, Ts...> - > { }; - } // meta_detail - - template class Pred, typename... Ts> - struct count_for_pack : meta_detail::count_for_pack { }; - - template class Pred, typename List> - struct count_for; - - template class Pred, typename... Args> - struct count_for> : count_for_pack {}; - - template class Pred, typename... Ts> - struct count_for_to_pack : meta_detail::count_for_pack { }; - - template class Pred, typename... Ts> - struct count_2_for_pack : meta_detail::count_2_for_pack<0, Pred, Ts...> { }; - - template - struct return_type { - typedef std::tuple type; - }; - - template - struct return_type { - typedef T type; - }; - - template<> - struct return_type<> { - typedef void type; - }; - - template - using return_type_t = typename return_type::type; - - namespace meta_detail { - template struct always_true : std::true_type {}; - struct is_invokable_tester { - template - always_true()(std::declval()...))> static test(int); - template - std::false_type static test(...); - }; - } // meta_detail - - template - struct is_invokable; - template - struct is_invokable : decltype(meta_detail::is_invokable_tester::test(0)) {}; - - namespace meta_detail { - - template>::value> - struct is_callable : std::is_function> {}; - - template - struct is_callable { - using yes = char; - using no = struct { char s[2]; }; - - struct F { void operator()(); }; - struct Derived : T, F {}; - template struct Check; - - template - static no test(Check*); - - template - static yes test(...); - - static const bool value = sizeof(test(0)) == sizeof(yes); - }; - - struct has_begin_end_impl { - template, - typename B = decltype(std::declval().begin()), - typename E = decltype(std::declval().end())> - static std::true_type test(int); - - template - static std::false_type test(...); - }; - - struct has_key_value_pair_impl { - template, - typename V = typename U::value_type, - typename F = decltype(std::declval().first), - typename S = decltype(std::declval().second)> - static std::true_type test(int); - - template - static std::false_type test(...); - }; - - template () < std::declval())> - std::true_type supports_op_less_test(const T&); - std::false_type supports_op_less_test(...); - template () == std::declval())> - std::true_type supports_op_equal_test(const T&); - std::false_type supports_op_equal_test(...); - template () <= std::declval())> - std::true_type supports_op_less_equal_test(const T&); - std::false_type supports_op_less_equal_test(...); - - } // meta_detail - - template - using supports_op_less = decltype(meta_detail::supports_op_less_test(std::declval())); - template - using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::declval())); - template - using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::declval())); - - template - struct is_callable : boolean::value> {}; - - template - struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test(0)) {}; - - template - struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test(0)) {}; - - template - using is_string_constructible = any, const char*>, std::is_same, char>, std::is_same, std::string>, std::is_same, std::initializer_list>>; - - template - using is_c_str = any< - std::is_same>, const char*>, - std::is_same>, char*>, - std::is_same, std::string> - >; - - template - struct is_move_only : all< - neg>, - neg>>, - std::is_move_constructible> - > {}; - - template - using is_not_move_only = neg>; - - namespace meta_detail { - template >> = meta::enabler> - decltype(auto) force_tuple(T&& x) { - return std::forward_as_tuple(std::forward(x)); - } - - template >> = meta::enabler> - decltype(auto) force_tuple(T&& x) { - return std::forward(x); - } - } // meta_detail - - template - decltype(auto) tuplefy(X&&... x) { - return std::tuple_cat(meta_detail::force_tuple(std::forward(x))...); - } - } // meta - namespace detail { - template - decltype(auto) forward_get(Tuple&& tuple) { - return std::forward>(std::get(tuple)); - } - - template - auto forward_tuple_impl(std::index_sequence, Tuple&& tuple) -> decltype(std::tuple(tuple))...>(forward_get(tuple)...)) { - return std::tuple(tuple))...>(std::move(std::get(tuple))...); - } - - template - auto forward_tuple(Tuple&& tuple) { - auto x = forward_tuple_impl(std::make_index_sequence>::value>(), std::forward(tuple)); - return x; - } - - template - auto unwrap(T&& item) -> decltype(std::forward(item)) { - return std::forward(item); - } - - template - T& unwrap(std::reference_wrapper arg) { - return arg.get(); - } - - template - auto deref(T&& item) -> decltype(std::forward(item)) { - return std::forward(item); - } - - template - inline T& deref(T* item) { - return *item; - } - - template - inline std::add_lvalue_reference_t deref(std::unique_ptr& item) { - return *item; - } - - template - inline std::add_lvalue_reference_t deref(std::shared_ptr& item) { - return *item; - } - - template - inline std::add_lvalue_reference_t deref(const std::unique_ptr& item) { - return *item; - } - - template - inline std::add_lvalue_reference_t deref(const std::shared_ptr& item) { - return *item; - } - - template - inline T* ptr(T& val) { - return std::addressof(val); - } - - template - inline T* ptr(std::reference_wrapper val) { - return std::addressof(val.get()); - } - - template - inline T* ptr(T* val) { - return val; - } - } // detail -} // sol - -#endif // SOL_TRAITS_HPP +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_TRAITS_HPP +#define SOL_TRAITS_HPP + +#include "tuple.hpp" +#include "bind_traits.hpp" +#include +#include +#include + +namespace sol { + template + using index_value = std::integral_constant; + + namespace meta { + template + struct identity { typedef T type; }; + + template + using identity_t = typename identity::type; + + template + struct is_tuple : std::false_type { }; + + template + struct is_tuple> : std::true_type { }; + + template + struct is_builtin_type : std::integral_constant::value || std::is_pointer::value || std::is_array::value> {}; + + template + struct unwrapped { + typedef T type; + }; + + template + struct unwrapped> { + typedef T type; + }; + + template + using unwrapped_t = typename unwrapped::type; + + template + struct unwrap_unqualified : unwrapped> {}; + + template + using unwrap_unqualified_t = typename unwrap_unqualified::type; + + template + struct remove_member_pointer; + + template + struct remove_member_pointer { + typedef R type; + }; + + template + struct remove_member_pointer { + typedef R type; + }; + + template + using remove_member_pointer_t = remove_member_pointer; + + template class Templ, typename T> + struct is_specialization_of : std::false_type { }; + template class Templ> + struct is_specialization_of> : std::true_type { }; + + template + struct all_same : std::true_type { }; + + template + struct all_same : std::integral_constant ::value && all_same::value> { }; + + template + struct any_same : std::false_type { }; + + template + struct any_same : std::integral_constant ::value || any_same::value> { }; + + template + using invoke_t = typename T::type; + + template + using boolean = std::integral_constant; + + template + using neg = boolean; + + template + using condition = std::conditional_t; + + template + struct all : boolean {}; + + template + struct all : condition, boolean> {}; + + template + struct any : boolean {}; + + template + struct any : condition, any> {}; + + enum class enable_t { + _ + }; + + constexpr const auto enabler = enable_t::_; + + template + using disable_if_t = std::enable_if_t; + + template + using enable = std::enable_if_t::value, enable_t>; + + template + using disable = std::enable_if_t>::value, enable_t>; + + template + using disable_any = std::enable_if_t>::value, enable_t>; + + template + struct find_in_pack_v : boolean { }; + + template + struct find_in_pack_v : any, find_in_pack_v> { }; + + namespace meta_detail { + template + struct index_in_pack : std::integral_constant { }; + + template + struct index_in_pack : std::conditional_t::value, std::integral_constant, index_in_pack> { }; + } + + template + struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> { }; + + template + struct index_in : meta_detail::index_in_pack<0, T, List> { }; + + template + struct index_in> : meta_detail::index_in_pack<0, T, Args...> { }; + + template + struct at_in_pack {}; + + template + using at_in_pack_t = typename at_in_pack::type; + + template + struct at_in_pack : std::conditional> {}; + + template + struct at_in_pack<0, Arg, Args...> { typedef Arg type; }; + + namespace meta_detail { + template class Pred, typename... Ts> + struct count_for_pack : std::integral_constant {}; + template class Pred, typename T, typename... Ts> + struct count_for_pack : std::conditional_t < sizeof...(Ts) == 0 || Limit < 2, + std::integral_constant(Limit != 0 && Pred::value)>, + count_for_pack(Pred::value), Pred, Ts...> + > { }; + template class Pred, typename... Ts> + struct count_2_for_pack : std::integral_constant {}; + template class Pred, typename T, typename U, typename... Ts> + struct count_2_for_pack : std::conditional_t(Pred::value)>, + count_2_for_pack(Pred::value), Pred, Ts...> + > { }; + } // meta_detail + + template class Pred, typename... Ts> + struct count_for_pack : meta_detail::count_for_pack { }; + + template class Pred, typename List> + struct count_for; + + template class Pred, typename... Args> + struct count_for> : count_for_pack {}; + + template class Pred, typename... Ts> + struct count_for_to_pack : meta_detail::count_for_pack { }; + + template class Pred, typename... Ts> + struct count_2_for_pack : meta_detail::count_2_for_pack<0, Pred, Ts...> { }; + + template + struct return_type { + typedef std::tuple type; + }; + + template + struct return_type { + typedef T type; + }; + + template<> + struct return_type<> { + typedef void type; + }; + + template + using return_type_t = typename return_type::type; + + namespace meta_detail { + template struct always_true : std::true_type {}; + struct is_invokable_tester { + template + always_true()(std::declval()...))> static test(int); + template + std::false_type static test(...); + }; + } // meta_detail + + template + struct is_invokable; + template + struct is_invokable : decltype(meta_detail::is_invokable_tester::test(0)) {}; + + namespace meta_detail { + + template>::value> + struct is_callable : std::is_function> {}; + + template + struct is_callable { + using yes = char; + using no = struct { char s[2]; }; + + struct F { void operator()(); }; + struct Derived : T, F {}; + template struct Check; + + template + static no test(Check*); + + template + static yes test(...); + + static const bool value = sizeof(test(0)) == sizeof(yes); + }; + + struct has_begin_end_impl { + template, + typename B = decltype(std::declval().begin()), + typename E = decltype(std::declval().end())> + static std::true_type test(int); + + template + static std::false_type test(...); + }; + + struct has_key_value_pair_impl { + template, + typename V = typename U::value_type, + typename F = decltype(std::declval().first), + typename S = decltype(std::declval().second)> + static std::true_type test(int); + + template + static std::false_type test(...); + }; + + template () < std::declval())> + std::true_type supports_op_less_test(const T&); + std::false_type supports_op_less_test(...); + template () == std::declval())> + std::true_type supports_op_equal_test(const T&); + std::false_type supports_op_equal_test(...); + template () <= std::declval())> + std::true_type supports_op_less_equal_test(const T&); + std::false_type supports_op_less_equal_test(...); + + } // meta_detail + + template + using supports_op_less = decltype(meta_detail::supports_op_less_test(std::declval())); + template + using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::declval())); + template + using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::declval())); + + template + struct is_callable : boolean::value> {}; + + template + struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test(0)) {}; + + template + struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test(0)) {}; + + template + using is_string_constructible = any, const char*>, std::is_same, char>, std::is_same, std::string>, std::is_same, std::initializer_list>>; + + template + using is_c_str = any< + std::is_same>, const char*>, + std::is_same>, char*>, + std::is_same, std::string> + >; + + template + struct is_move_only : all< + neg>, + neg>>, + std::is_move_constructible> + > {}; + + template + using is_not_move_only = neg>; + + namespace meta_detail { + template >> = meta::enabler> + decltype(auto) force_tuple(T&& x) { + return std::forward_as_tuple(std::forward(x)); + } + + template >> = meta::enabler> + decltype(auto) force_tuple(T&& x) { + return std::forward(x); + } + } // meta_detail + + template + decltype(auto) tuplefy(X&&... x) { + return std::tuple_cat(meta_detail::force_tuple(std::forward(x))...); + } + } // meta + namespace detail { + template + decltype(auto) forward_get(Tuple&& tuple) { + return std::forward>(std::get(tuple)); + } + + template + auto forward_tuple_impl(std::index_sequence, Tuple&& tuple) -> decltype(std::tuple(tuple))...>(forward_get(tuple)...)) { + return std::tuple(tuple))...>(std::move(std::get(tuple))...); + } + + template + auto forward_tuple(Tuple&& tuple) { + auto x = forward_tuple_impl(std::make_index_sequence>::value>(), std::forward(tuple)); + return x; + } + + template + auto unwrap(T&& item) -> decltype(std::forward(item)) { + return std::forward(item); + } + + template + T& unwrap(std::reference_wrapper arg) { + return arg.get(); + } + + template + auto deref(T&& item) -> decltype(std::forward(item)) { + return std::forward(item); + } + + template + inline T& deref(T* item) { + return *item; + } + + template + inline std::add_lvalue_reference_t deref(std::unique_ptr& item) { + return *item; + } + + template + inline std::add_lvalue_reference_t deref(std::shared_ptr& item) { + return *item; + } + + template + inline std::add_lvalue_reference_t deref(const std::unique_ptr& item) { + return *item; + } + + template + inline std::add_lvalue_reference_t deref(const std::shared_ptr& item) { + return *item; + } + + template + inline T* ptr(T& val) { + return std::addressof(val); + } + + template + inline T* ptr(std::reference_wrapper val) { + return std::addressof(val.get()); + } + + template + inline T* ptr(T* val) { + return val; + } + } // detail +} // sol + +#endif // SOL_TRAITS_HPP diff --git a/test_simple_usertypes.cpp b/test_simple_usertypes.cpp index ca3e7cdc..4b25686c 100644 --- a/test_simple_usertypes.cpp +++ b/test_simple_usertypes.cpp @@ -461,3 +461,29 @@ TEST_CASE("usertype/simple-table-append", "Ensure that appending to the meta tab lua.script("assert(ua:func() == 5000)"); ); } + +TEST_CASE("usertype/simple-class-propogation", "make sure methods and variables from base classes work properly in SAFE_USERTYPE mode") { + class A { + public: + int var = 200; + int thing() const { return 123; } + }; + + class B : public A { + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_simple_usertype("B", + sol::default_constructor, + "thing", &B::thing, + "var", &B::var + ); + + lua.script(R"( + b = B.new() + print(b.var) + b:thing() +)"); +}