mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
make sure member functions for simple usertypes propogate their desired type.
This commit is contained in:
parent
37420dcdc0
commit
23e3f2c26d
|
@ -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<typename T>
|
||||
struct class_indicator {};
|
||||
}
|
||||
namespace stack {
|
||||
template<typename... Sigs>
|
||||
struct pusher<function_sig<Sigs...>> {
|
||||
|
@ -8770,12 +8774,19 @@ namespace sol {
|
|||
select_convertible(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
template <typename Fx, typename T, typename... Args, meta::disable<meta::is_specialization_of<function_detail::class_indicator, meta::unqualified_t<T>>> = meta::enabler>
|
||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference;
|
||||
select_reference_member_variable(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename C>
|
||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator<C>) {
|
||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::call;
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template <typename Fx>
|
||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) {
|
||||
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
|
||||
|
@ -8808,12 +8819,19 @@ namespace sol {
|
|||
select_member_variable(std::is_member_object_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
template <typename Fx, typename T, typename... Args, meta::disable<meta::is_specialization_of<function_detail::class_indicator, meta::unqualified_t<T>>> = meta::enabler>
|
||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference;
|
||||
select_reference_member_function(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename C>
|
||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator<C>) {
|
||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx>::call;
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template <typename Fx>
|
||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx) {
|
||||
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
|
||||
|
@ -8886,9 +8904,9 @@ namespace sol {
|
|||
|
||||
template<typename Signature>
|
||||
struct pusher<Signature, std::enable_if_t<std::is_member_pointer<Signature>::value>> {
|
||||
template <typename F>
|
||||
static int push(lua_State* L, F&& f) {
|
||||
return pusher<function_sig<>>{}.push(L, std::forward<F>(f));
|
||||
template <typename F, typename... Args>
|
||||
static int push(lua_State* L, F&& f, Args&&... args) {
|
||||
return pusher<function_sig<>>{}.push(L, std::forward<F>(f), std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -10807,6 +10825,26 @@ namespace sol {
|
|||
hint->second = std::move(o);
|
||||
}
|
||||
|
||||
template <typename N, typename F>
|
||||
void add_member_function(std::true_type, lua_State* L, N&& n, F&& f) {
|
||||
object o = make_object<F>(L, std::forward<F>(f), function_detail::class_indicator<T>());
|
||||
if (std::is_same<meta::unqualified_t<N>, call_construction>::value) {
|
||||
callconstructfunc = std::move(o);
|
||||
return;
|
||||
}
|
||||
insert(std::forward<N>(n), std::move(o));
|
||||
}
|
||||
|
||||
template <typename N, typename F>
|
||||
void add_member_function(std::false_type, lua_State* L, N&& n, F&& f) {
|
||||
object o = make_object<F>(L, std::forward<F>(f));
|
||||
if (std::is_same<meta::unqualified_t<N>, call_construction>::value) {
|
||||
callconstructfunc = std::move(o);
|
||||
return;
|
||||
}
|
||||
insert(std::forward<N>(n), std::move(o));
|
||||
}
|
||||
|
||||
template <typename N, typename F, meta::enable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler>
|
||||
void add_function(lua_State* L, N&& n, F&& f) {
|
||||
insert(std::forward<N>(n), make_object(L, as_function_reference(std::forward<F>(f))));
|
||||
|
@ -10814,12 +10852,7 @@ namespace sol {
|
|||
|
||||
template <typename N, typename F, meta::disable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler>
|
||||
void add_function(lua_State* L, N&& n, F&& f) {
|
||||
object o = make_object(L, std::forward<F>(f));
|
||||
if (std::is_same<meta::unqualified_t<N>, call_construction>::value) {
|
||||
callconstructfunc = std::move(o);
|
||||
return;
|
||||
}
|
||||
insert(std::forward<N>(n), std::move(o));
|
||||
add_member_function(std::is_member_pointer<meta::unwrap_unqualified_t<F>>(), L, std::forward<N>(n), std::forward<F>(f));
|
||||
}
|
||||
|
||||
template <typename N, typename F, meta::disable<is_variable_binding<meta::unqualified_t<F>>> = meta::enabler>
|
||||
|
|
|
@ -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<typename... Sigs>
|
||||
struct pusher<function_sig<Sigs...>> {
|
||||
template <typename... Sig, typename Fx, typename... Args>
|
||||
static void select_convertible(std::false_type, types<Sig...>, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
|
||||
typedef function_detail::functor_function<clean_fx> F;
|
||||
set_fx<F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename R, typename... A, typename Fx, typename... Args>
|
||||
static void select_convertible(std::true_type, types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
using fx_ptr_t = R(*)(A...);
|
||||
fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
|
||||
select_function(std::true_type(), L, fxptr, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename R, typename... A, typename Fx, typename... Args>
|
||||
static void select_convertible(types<R(A...)> t, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
typedef std::decay_t<meta::unwrap_unqualified_t<Fx>> raw_fx_t;
|
||||
typedef R(*fx_ptr_t)(A...);
|
||||
typedef std::is_convertible<raw_fx_t, fx_ptr_t> is_convertible;
|
||||
select_convertible(is_convertible(), t, L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
typedef meta::function_signature_t<meta::unwrap_unqualified_t<Fx>> Sig;
|
||||
select_convertible(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
|
||||
typedef function_detail::member_variable<meta::unwrap_unqualified_t<T>, clean_fx> F;
|
||||
set_fx<F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef std::decay_t<Fx> dFx;
|
||||
dFx memfxptr(std::forward<Fx>(fx));
|
||||
auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
lua_CFunction freefunc = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>>::call;
|
||||
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
|
||||
upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
select_convertible(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference;
|
||||
select_reference_member_variable(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx>
|
||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) {
|
||||
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
|
||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::call;
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef std::decay_t<Fx> clean_fx;
|
||||
typedef function_detail::member_function<meta::unwrap_unqualified_t<T>, clean_fx> F;
|
||||
set_fx<F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef std::decay_t<Fx> dFx;
|
||||
dFx memfxptr(std::forward<Fx>(fx));
|
||||
auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>>::call;
|
||||
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
|
||||
upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
select_member_variable(std::is_member_object_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference;
|
||||
select_reference_member_function(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx>
|
||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx) {
|
||||
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
|
||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx>::call;
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
select_member_function(std::is_member_function_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx>::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 <typename Fx, typename... Args>
|
||||
static void select(lua_State* L, Fx&& fx, Args&&... args) {
|
||||
select_function(std::is_function<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void set_fx(lua_State* L, Args&&... args) {
|
||||
lua_CFunction freefunc = function_detail::call<meta::unqualified_t<Fx>>;
|
||||
|
||||
stack::push<user<Fx>>(L, std::forward<Args>(args)...);
|
||||
stack::push(L, c_closure(freefunc, 1));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
static int push(lua_State* L, Args&&... args) {
|
||||
// Set will always place one thing (function) on the stack
|
||||
select(L, std::forward<Args>(args)...);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
struct pusher<function_arguments<T, Args...>> {
|
||||
template <std::size_t... I, typename FP>
|
||||
static int push_func(std::index_sequence<I...>, lua_State* L, FP&& fp) {
|
||||
return stack::push<T>(L, detail::forward_get<I>(fp.arguments)...);
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const function_arguments<T, Args...>& fp) {
|
||||
return push_func(std::make_index_sequence<sizeof...(Args)>(), L, fp);
|
||||
}
|
||||
|
||||
static int push(lua_State* L, function_arguments<T, Args...>&& fp) {
|
||||
return push_func(std::make_index_sequence<sizeof...(Args)>(), L, std::move(fp));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Signature>
|
||||
struct pusher<std::function<Signature>> {
|
||||
static int push(lua_State* L, std::function<Signature> fx) {
|
||||
return pusher<function_sig<Signature>>{}.push(L, std::move(fx));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Signature>
|
||||
struct pusher<Signature, std::enable_if_t<std::is_member_pointer<Signature>::value>> {
|
||||
template <typename F>
|
||||
static int push(lua_State* L, F&& f) {
|
||||
return pusher<function_sig<>>{}.push(L, std::forward<F>(f));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Signature>
|
||||
struct pusher<Signature, std::enable_if_t<meta::all<std::is_function<Signature>, meta::neg<std::is_same<Signature, lua_CFunction>>, meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>>::value>> {
|
||||
template <typename F>
|
||||
static int push(lua_State* L, F&& f) {
|
||||
return pusher<function_sig<>>{}.push(L, std::forward<F>(f));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Functions>
|
||||
struct pusher<overload_set<Functions...>> {
|
||||
static int push(lua_State* L, overload_set<Functions...>&& set) {
|
||||
typedef function_detail::overloaded_function<Functions...> F;
|
||||
pusher<function_sig<>>{}.set_fx<F>(L, std::move(set.functions));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const overload_set<Functions...>& set) {
|
||||
typedef function_detail::overloaded_function<Functions...> F;
|
||||
pusher<function_sig<>>{}.set_fx<F>(L, set.functions);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct pusher<protect_t<T>> {
|
||||
static int push(lua_State* L, protect_t<T>&& pw) {
|
||||
lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>>;
|
||||
int closures = stack::push<user<protect_t<T>>>(L, std::move(pw.value));
|
||||
return stack::push(L, c_closure(cf, closures));
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const protect_t<T>& pw) {
|
||||
lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>>;
|
||||
int closures = stack::push<user<protect_t<T>>>(L, pw.value);
|
||||
return stack::push(L, c_closure(cf, closures));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, typename G>
|
||||
struct pusher<property_wrapper<F, G>, std::enable_if_t<!std::is_void<F>::value && !std::is_void<G>::value>> {
|
||||
static int push(lua_State* L, property_wrapper<F, G>&& pw) {
|
||||
return stack::push(L, sol::overload(std::move(pw.read), std::move(pw.write)));
|
||||
}
|
||||
static int push(lua_State* L, const property_wrapper<F, G>& pw) {
|
||||
return stack::push(L, sol::overload(pw.read, pw.write));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
struct pusher<property_wrapper<F, void>> {
|
||||
static int push(lua_State* L, property_wrapper<F, void>&& pw) {
|
||||
return stack::push(L, std::move(pw.read));
|
||||
}
|
||||
static int push(lua_State* L, const property_wrapper<F, void>& pw) {
|
||||
return stack::push(L, pw.read);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
struct pusher<property_wrapper<void, F>> {
|
||||
static int push(lua_State* L, property_wrapper<void, F>&& pw) {
|
||||
return stack::push(L, std::move(pw.write));
|
||||
}
|
||||
static int push(lua_State* L, const property_wrapper<void, F>& pw) {
|
||||
return stack::push(L, pw.write);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct pusher<var_wrapper<T>> {
|
||||
static int push(lua_State* L, var_wrapper<T>&& vw) {
|
||||
return stack::push(L, std::move(vw.value));
|
||||
}
|
||||
static int push(lua_State* L, const var_wrapper<T>& vw) {
|
||||
return stack::push(L, vw.value);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Functions>
|
||||
struct pusher<factory_wrapper<Functions...>> {
|
||||
static int push(lua_State* L, const factory_wrapper<Functions...>& fw) {
|
||||
typedef function_detail::overloaded_function<Functions...> F;
|
||||
pusher<function_sig<>>{}.set_fx<F>(L, fw.functions);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int push(lua_State* L, factory_wrapper<Functions...>&& fw) {
|
||||
typedef function_detail::overloaded_function<Functions...> F;
|
||||
pusher<function_sig<>>{}.set_fx<F>(L, std::move(fw.functions));
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename... Lists>
|
||||
struct pusher<detail::tagged<T, constructor_list<Lists...>>> {
|
||||
static int push(lua_State* L, detail::tagged<T, constructor_list<Lists...>>) {
|
||||
lua_CFunction cf = call_detail::construct<T, Lists...>;
|
||||
return stack::push(L, cf);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename... Fxs>
|
||||
struct pusher<detail::tagged<T, constructor_wrapper<Fxs...>>> {
|
||||
template <typename C>
|
||||
static int push(lua_State* L, C&& c) {
|
||||
lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>>;
|
||||
int closures = stack::push<user<constructor_wrapper<Fxs...>>>(L, std::forward<C>(c));
|
||||
return stack::push(L, c_closure(cf, closures));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct pusher<detail::tagged<T, destructor_wrapper<void>>> {
|
||||
static int push(lua_State* L, destructor_wrapper<void>) {
|
||||
lua_CFunction cf = detail::usertype_alloc_destroy<T>;
|
||||
return stack::push(L, cf);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Fx>
|
||||
struct pusher<detail::tagged<T, destructor_wrapper<Fx>>> {
|
||||
static int push(lua_State* L, destructor_wrapper<Fx> c) {
|
||||
lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>>;
|
||||
int closures = stack::push<user<T>>(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<typename T>
|
||||
struct class_indicator {};
|
||||
}
|
||||
namespace stack {
|
||||
template<typename... Sigs>
|
||||
struct pusher<function_sig<Sigs...>> {
|
||||
template <typename... Sig, typename Fx, typename... Args>
|
||||
static void select_convertible(std::false_type, types<Sig...>, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
|
||||
typedef function_detail::functor_function<clean_fx> F;
|
||||
set_fx<F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename R, typename... A, typename Fx, typename... Args>
|
||||
static void select_convertible(std::true_type, types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
using fx_ptr_t = R(*)(A...);
|
||||
fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
|
||||
select_function(std::true_type(), L, fxptr, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename R, typename... A, typename Fx, typename... Args>
|
||||
static void select_convertible(types<R(A...)> t, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
typedef std::decay_t<meta::unwrap_unqualified_t<Fx>> raw_fx_t;
|
||||
typedef R(*fx_ptr_t)(A...);
|
||||
typedef std::is_convertible<raw_fx_t, fx_ptr_t> is_convertible;
|
||||
select_convertible(is_convertible(), t, L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
typedef meta::function_signature_t<meta::unwrap_unqualified_t<Fx>> Sig;
|
||||
select_convertible(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
|
||||
typedef function_detail::member_variable<meta::unwrap_unqualified_t<T>, clean_fx> F;
|
||||
set_fx<F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef std::decay_t<Fx> dFx;
|
||||
dFx memfxptr(std::forward<Fx>(fx));
|
||||
auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
lua_CFunction freefunc = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>>::call;
|
||||
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
|
||||
upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
select_convertible(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args, meta::disable<meta::is_specialization_of<function_detail::class_indicator, meta::unqualified_t<T>>> = meta::enabler>
|
||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference;
|
||||
select_reference_member_variable(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename C>
|
||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator<C>) {
|
||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::call;
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template <typename Fx>
|
||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) {
|
||||
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
|
||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::call;
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef std::decay_t<Fx> clean_fx;
|
||||
typedef function_detail::member_function<meta::unwrap_unqualified_t<T>, clean_fx> F;
|
||||
set_fx<F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef std::decay_t<Fx> dFx;
|
||||
dFx memfxptr(std::forward<Fx>(fx));
|
||||
auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>>::call;
|
||||
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
|
||||
upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
select_member_variable(std::is_member_object_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args, meta::disable<meta::is_specialization_of<function_detail::class_indicator, meta::unqualified_t<T>>> = meta::enabler>
|
||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference;
|
||||
select_reference_member_function(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename C>
|
||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator<C>) {
|
||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx>::call;
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template <typename Fx>
|
||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx) {
|
||||
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
|
||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx>::call;
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
select_member_function(std::is_member_function_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx>::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 <typename Fx, typename... Args>
|
||||
static void select(lua_State* L, Fx&& fx, Args&&... args) {
|
||||
select_function(std::is_function<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void set_fx(lua_State* L, Args&&... args) {
|
||||
lua_CFunction freefunc = function_detail::call<meta::unqualified_t<Fx>>;
|
||||
|
||||
stack::push<user<Fx>>(L, std::forward<Args>(args)...);
|
||||
stack::push(L, c_closure(freefunc, 1));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
static int push(lua_State* L, Args&&... args) {
|
||||
// Set will always place one thing (function) on the stack
|
||||
select(L, std::forward<Args>(args)...);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
struct pusher<function_arguments<T, Args...>> {
|
||||
template <std::size_t... I, typename FP>
|
||||
static int push_func(std::index_sequence<I...>, lua_State* L, FP&& fp) {
|
||||
return stack::push<T>(L, detail::forward_get<I>(fp.arguments)...);
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const function_arguments<T, Args...>& fp) {
|
||||
return push_func(std::make_index_sequence<sizeof...(Args)>(), L, fp);
|
||||
}
|
||||
|
||||
static int push(lua_State* L, function_arguments<T, Args...>&& fp) {
|
||||
return push_func(std::make_index_sequence<sizeof...(Args)>(), L, std::move(fp));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Signature>
|
||||
struct pusher<std::function<Signature>> {
|
||||
static int push(lua_State* L, std::function<Signature> fx) {
|
||||
return pusher<function_sig<Signature>>{}.push(L, std::move(fx));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Signature>
|
||||
struct pusher<Signature, std::enable_if_t<std::is_member_pointer<Signature>::value>> {
|
||||
template <typename F, typename... Args>
|
||||
static int push(lua_State* L, F&& f, Args&&... args) {
|
||||
return pusher<function_sig<>>{}.push(L, std::forward<F>(f), std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Signature>
|
||||
struct pusher<Signature, std::enable_if_t<meta::all<std::is_function<Signature>, meta::neg<std::is_same<Signature, lua_CFunction>>, meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>>::value>> {
|
||||
template <typename F>
|
||||
static int push(lua_State* L, F&& f) {
|
||||
return pusher<function_sig<>>{}.push(L, std::forward<F>(f));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Functions>
|
||||
struct pusher<overload_set<Functions...>> {
|
||||
static int push(lua_State* L, overload_set<Functions...>&& set) {
|
||||
typedef function_detail::overloaded_function<Functions...> F;
|
||||
pusher<function_sig<>>{}.set_fx<F>(L, std::move(set.functions));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const overload_set<Functions...>& set) {
|
||||
typedef function_detail::overloaded_function<Functions...> F;
|
||||
pusher<function_sig<>>{}.set_fx<F>(L, set.functions);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct pusher<protect_t<T>> {
|
||||
static int push(lua_State* L, protect_t<T>&& pw) {
|
||||
lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>>;
|
||||
int closures = stack::push<user<protect_t<T>>>(L, std::move(pw.value));
|
||||
return stack::push(L, c_closure(cf, closures));
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const protect_t<T>& pw) {
|
||||
lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>>;
|
||||
int closures = stack::push<user<protect_t<T>>>(L, pw.value);
|
||||
return stack::push(L, c_closure(cf, closures));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, typename G>
|
||||
struct pusher<property_wrapper<F, G>, std::enable_if_t<!std::is_void<F>::value && !std::is_void<G>::value>> {
|
||||
static int push(lua_State* L, property_wrapper<F, G>&& pw) {
|
||||
return stack::push(L, sol::overload(std::move(pw.read), std::move(pw.write)));
|
||||
}
|
||||
static int push(lua_State* L, const property_wrapper<F, G>& pw) {
|
||||
return stack::push(L, sol::overload(pw.read, pw.write));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
struct pusher<property_wrapper<F, void>> {
|
||||
static int push(lua_State* L, property_wrapper<F, void>&& pw) {
|
||||
return stack::push(L, std::move(pw.read));
|
||||
}
|
||||
static int push(lua_State* L, const property_wrapper<F, void>& pw) {
|
||||
return stack::push(L, pw.read);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
struct pusher<property_wrapper<void, F>> {
|
||||
static int push(lua_State* L, property_wrapper<void, F>&& pw) {
|
||||
return stack::push(L, std::move(pw.write));
|
||||
}
|
||||
static int push(lua_State* L, const property_wrapper<void, F>& pw) {
|
||||
return stack::push(L, pw.write);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct pusher<var_wrapper<T>> {
|
||||
static int push(lua_State* L, var_wrapper<T>&& vw) {
|
||||
return stack::push(L, std::move(vw.value));
|
||||
}
|
||||
static int push(lua_State* L, const var_wrapper<T>& vw) {
|
||||
return stack::push(L, vw.value);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Functions>
|
||||
struct pusher<factory_wrapper<Functions...>> {
|
||||
static int push(lua_State* L, const factory_wrapper<Functions...>& fw) {
|
||||
typedef function_detail::overloaded_function<Functions...> F;
|
||||
pusher<function_sig<>>{}.set_fx<F>(L, fw.functions);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int push(lua_State* L, factory_wrapper<Functions...>&& fw) {
|
||||
typedef function_detail::overloaded_function<Functions...> F;
|
||||
pusher<function_sig<>>{}.set_fx<F>(L, std::move(fw.functions));
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename... Lists>
|
||||
struct pusher<detail::tagged<T, constructor_list<Lists...>>> {
|
||||
static int push(lua_State* L, detail::tagged<T, constructor_list<Lists...>>) {
|
||||
lua_CFunction cf = call_detail::construct<T, Lists...>;
|
||||
return stack::push(L, cf);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename... Fxs>
|
||||
struct pusher<detail::tagged<T, constructor_wrapper<Fxs...>>> {
|
||||
template <typename C>
|
||||
static int push(lua_State* L, C&& c) {
|
||||
lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>>;
|
||||
int closures = stack::push<user<constructor_wrapper<Fxs...>>>(L, std::forward<C>(c));
|
||||
return stack::push(L, c_closure(cf, closures));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct pusher<detail::tagged<T, destructor_wrapper<void>>> {
|
||||
static int push(lua_State* L, destructor_wrapper<void>) {
|
||||
lua_CFunction cf = detail::usertype_alloc_destroy<T>;
|
||||
return stack::push(L, cf);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Fx>
|
||||
struct pusher<detail::tagged<T, destructor_wrapper<Fx>>> {
|
||||
static int push(lua_State* L, destructor_wrapper<Fx> c) {
|
||||
lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>>;
|
||||
int closures = stack::push<user<T>>(L, std::move(c));
|
||||
return stack::push(L, c_closure(cf, closures));
|
||||
}
|
||||
};
|
||||
|
||||
} // stack
|
||||
} // sol
|
||||
|
||||
#endif // SOL_FUNCTION_TYPES_HPP
|
||||
|
|
|
@ -208,6 +208,26 @@ namespace sol {
|
|||
hint->second = std::move(o);
|
||||
}
|
||||
|
||||
template <typename N, typename F>
|
||||
void add_member_function(std::true_type, lua_State* L, N&& n, F&& f) {
|
||||
object o = make_object<F>(L, std::forward<F>(f), function_detail::class_indicator<T>());
|
||||
if (std::is_same<meta::unqualified_t<N>, call_construction>::value) {
|
||||
callconstructfunc = std::move(o);
|
||||
return;
|
||||
}
|
||||
insert(std::forward<N>(n), std::move(o));
|
||||
}
|
||||
|
||||
template <typename N, typename F>
|
||||
void add_member_function(std::false_type, lua_State* L, N&& n, F&& f) {
|
||||
object o = make_object<F>(L, std::forward<F>(f));
|
||||
if (std::is_same<meta::unqualified_t<N>, call_construction>::value) {
|
||||
callconstructfunc = std::move(o);
|
||||
return;
|
||||
}
|
||||
insert(std::forward<N>(n), std::move(o));
|
||||
}
|
||||
|
||||
template <typename N, typename F, meta::enable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler>
|
||||
void add_function(lua_State* L, N&& n, F&& f) {
|
||||
insert(std::forward<N>(n), make_object(L, as_function_reference(std::forward<F>(f))));
|
||||
|
@ -215,12 +235,7 @@ namespace sol {
|
|||
|
||||
template <typename N, typename F, meta::disable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler>
|
||||
void add_function(lua_State* L, N&& n, F&& f) {
|
||||
object o = make_object(L, std::forward<F>(f));
|
||||
if (std::is_same<meta::unqualified_t<N>, call_construction>::value) {
|
||||
callconstructfunc = std::move(o);
|
||||
return;
|
||||
}
|
||||
insert(std::forward<N>(n), std::move(o));
|
||||
add_member_function(std::is_member_pointer<meta::unwrap_unqualified_t<F>>(), L, std::forward<N>(n), std::forward<F>(f));
|
||||
}
|
||||
|
||||
template <typename N, typename F, meta::disable<is_variable_binding<meta::unqualified_t<F>>> = meta::enabler>
|
||||
|
|
856
sol/traits.hpp
856
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 <type_traits>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
namespace sol {
|
||||
template<std::size_t I>
|
||||
using index_value = std::integral_constant<std::size_t, I>;
|
||||
|
||||
namespace meta {
|
||||
template<typename T>
|
||||
struct identity { typedef T type; };
|
||||
|
||||
template<typename T>
|
||||
using identity_t = typename identity<T>::type;
|
||||
|
||||
template<typename... Args>
|
||||
struct is_tuple : std::false_type { };
|
||||
|
||||
template<typename... Args>
|
||||
struct is_tuple<std::tuple<Args...>> : std::true_type { };
|
||||
|
||||
template <typename T>
|
||||
struct is_builtin_type : std::integral_constant<bool, std::is_arithmetic<T>::value || std::is_pointer<T>::value || std::is_array<T>::value> {};
|
||||
|
||||
template<typename T>
|
||||
struct unwrapped {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct unwrapped<std::reference_wrapper<T>> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using unwrapped_t = typename unwrapped<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct unwrap_unqualified : unwrapped<unqualified_t<T>> {};
|
||||
|
||||
template <typename T>
|
||||
using unwrap_unqualified_t = typename unwrap_unqualified<T>::type;
|
||||
|
||||
template<typename T>
|
||||
struct remove_member_pointer;
|
||||
|
||||
template<typename R, typename T>
|
||||
struct remove_member_pointer<R T::*> {
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename T>
|
||||
struct remove_member_pointer<R T::* const> {
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using remove_member_pointer_t = remove_member_pointer<T>;
|
||||
|
||||
template<template<typename...> class Templ, typename T>
|
||||
struct is_specialization_of : std::false_type { };
|
||||
template<typename... T, template<typename...> class Templ>
|
||||
struct is_specialization_of<Templ, Templ<T...>> : std::true_type { };
|
||||
|
||||
template<class T, class...>
|
||||
struct all_same : std::true_type { };
|
||||
|
||||
template<class T, class U, class... Args>
|
||||
struct all_same<T, U, Args...> : std::integral_constant <bool, std::is_same<T, U>::value && all_same<T, Args...>::value> { };
|
||||
|
||||
template<class T, class...>
|
||||
struct any_same : std::false_type { };
|
||||
|
||||
template<class T, class U, class... Args>
|
||||
struct any_same<T, U, Args...> : std::integral_constant <bool, std::is_same<T, U>::value || any_same<T, Args...>::value> { };
|
||||
|
||||
template<typename T>
|
||||
using invoke_t = typename T::type;
|
||||
|
||||
template<bool B>
|
||||
using boolean = std::integral_constant<bool, B>;
|
||||
|
||||
template<typename T>
|
||||
using neg = boolean<!T::value>;
|
||||
|
||||
template<typename Condition, typename Then, typename Else>
|
||||
using condition = std::conditional_t<Condition::value, Then, Else>;
|
||||
|
||||
template<typename... Args>
|
||||
struct all : boolean<true> {};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
struct all<T, Args...> : condition<T, all<Args...>, boolean<false>> {};
|
||||
|
||||
template<typename... Args>
|
||||
struct any : boolean<false> {};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
struct any<T, Args...> : condition<T, boolean<true>, any<Args...>> {};
|
||||
|
||||
enum class enable_t {
|
||||
_
|
||||
};
|
||||
|
||||
constexpr const auto enabler = enable_t::_;
|
||||
|
||||
template<bool value, typename T = void>
|
||||
using disable_if_t = std::enable_if_t<!value, T>;
|
||||
|
||||
template<typename... Args>
|
||||
using enable = std::enable_if_t<all<Args...>::value, enable_t>;
|
||||
|
||||
template<typename... Args>
|
||||
using disable = std::enable_if_t<neg<all<Args...>>::value, enable_t>;
|
||||
|
||||
template<typename... Args>
|
||||
using disable_any = std::enable_if_t<neg<any<Args...>>::value, enable_t>;
|
||||
|
||||
template<typename V, typename... Vs>
|
||||
struct find_in_pack_v : boolean<false> { };
|
||||
|
||||
template<typename V, typename Vs1, typename... Vs>
|
||||
struct find_in_pack_v<V, Vs1, Vs...> : any<boolean<(V::value == Vs1::value)>, find_in_pack_v<V, Vs...>> { };
|
||||
|
||||
namespace meta_detail {
|
||||
template<std::size_t I, typename T, typename... Args>
|
||||
struct index_in_pack : std::integral_constant<std::size_t, SIZE_MAX> { };
|
||||
|
||||
template<std::size_t I, typename T, typename T1, typename... Args>
|
||||
struct index_in_pack<I, T, T1, Args...> : std::conditional_t<std::is_same<T, T1>::value, std::integral_constant<std::ptrdiff_t, I>, index_in_pack<I + 1, T, Args...>> { };
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> { };
|
||||
|
||||
template<typename T, typename List>
|
||||
struct index_in : meta_detail::index_in_pack<0, T, List> { };
|
||||
|
||||
template<typename T, typename... Args>
|
||||
struct index_in<T, types<Args...>> : meta_detail::index_in_pack<0, T, Args...> { };
|
||||
|
||||
template<std::size_t I, typename... Args>
|
||||
struct at_in_pack {};
|
||||
|
||||
template<std::size_t I, typename... Args>
|
||||
using at_in_pack_t = typename at_in_pack<I, Args...>::type;
|
||||
|
||||
template<std::size_t I, typename Arg, typename... Args>
|
||||
struct at_in_pack<I, Arg, Args...> : std::conditional<I == 0, Arg, at_in_pack_t<I - 1, Args...>> {};
|
||||
|
||||
template<typename Arg, typename... Args>
|
||||
struct at_in_pack<0, Arg, Args...> { typedef Arg type; };
|
||||
|
||||
namespace meta_detail {
|
||||
template<std::size_t Limit, std::size_t I, template<typename...> class Pred, typename... Ts>
|
||||
struct count_for_pack : std::integral_constant<std::size_t, 0> {};
|
||||
template<std::size_t Limit, std::size_t I, template<typename...> class Pred, typename T, typename... Ts>
|
||||
struct count_for_pack<Limit, I, Pred, T, Ts...> : std::conditional_t < sizeof...(Ts) == 0 || Limit < 2,
|
||||
std::integral_constant<std::size_t, I + static_cast<std::size_t>(Limit != 0 && Pred<T>::value)>,
|
||||
count_for_pack<Limit - 1, I + static_cast<std::size_t>(Pred<T>::value), Pred, Ts...>
|
||||
> { };
|
||||
template<std::size_t I, template<typename...> class Pred, typename... Ts>
|
||||
struct count_2_for_pack : std::integral_constant<std::size_t, 0> {};
|
||||
template<std::size_t I, template<typename...> class Pred, typename T, typename U, typename... Ts>
|
||||
struct count_2_for_pack<I, Pred, T, U, Ts...> : std::conditional_t<sizeof...(Ts) == 0,
|
||||
std::integral_constant<std::size_t, I + static_cast<std::size_t>(Pred<T>::value)>,
|
||||
count_2_for_pack<I + static_cast<std::size_t>(Pred<T>::value), Pred, Ts...>
|
||||
> { };
|
||||
} // meta_detail
|
||||
|
||||
template<template<typename...> class Pred, typename... Ts>
|
||||
struct count_for_pack : meta_detail::count_for_pack<sizeof...(Ts), 0, Pred, Ts...> { };
|
||||
|
||||
template<template<typename...> class Pred, typename List>
|
||||
struct count_for;
|
||||
|
||||
template<template<typename...> class Pred, typename... Args>
|
||||
struct count_for<Pred, types<Args...>> : count_for_pack<Pred, Args...> {};
|
||||
|
||||
template<std::size_t Limit, template<typename...> class Pred, typename... Ts>
|
||||
struct count_for_to_pack : meta_detail::count_for_pack<Limit, 0, Pred, Ts...> { };
|
||||
|
||||
template<template<typename...> class Pred, typename... Ts>
|
||||
struct count_2_for_pack : meta_detail::count_2_for_pack<0, Pred, Ts...> { };
|
||||
|
||||
template<typename... Args>
|
||||
struct return_type {
|
||||
typedef std::tuple<Args...> type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct return_type<T> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct return_type<> {
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
using return_type_t = typename return_type<Args...>::type;
|
||||
|
||||
namespace meta_detail {
|
||||
template <typename> struct always_true : std::true_type {};
|
||||
struct is_invokable_tester {
|
||||
template <typename Fun, typename... Args>
|
||||
always_true<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int);
|
||||
template <typename...>
|
||||
std::false_type static test(...);
|
||||
};
|
||||
} // meta_detail
|
||||
|
||||
template <typename T>
|
||||
struct is_invokable;
|
||||
template <typename Fun, typename... Args>
|
||||
struct is_invokable<Fun(Args...)> : decltype(meta_detail::is_invokable_tester::test<Fun, Args...>(0)) {};
|
||||
|
||||
namespace meta_detail {
|
||||
|
||||
template<typename T, bool isclass = std::is_class<unqualified_t<T>>::value>
|
||||
struct is_callable : std::is_function<std::remove_pointer_t<T>> {};
|
||||
|
||||
template<typename T>
|
||||
struct is_callable<T, true> {
|
||||
using yes = char;
|
||||
using no = struct { char s[2]; };
|
||||
|
||||
struct F { void operator()(); };
|
||||
struct Derived : T, F {};
|
||||
template<typename U, U> struct Check;
|
||||
|
||||
template<typename V>
|
||||
static no test(Check<void (F::*)(), &V::operator()>*);
|
||||
|
||||
template<typename>
|
||||
static yes test(...);
|
||||
|
||||
static const bool value = sizeof(test<Derived>(0)) == sizeof(yes);
|
||||
};
|
||||
|
||||
struct has_begin_end_impl {
|
||||
template<typename T, typename U = unqualified_t<T>,
|
||||
typename B = decltype(std::declval<U&>().begin()),
|
||||
typename E = decltype(std::declval<U&>().end())>
|
||||
static std::true_type test(int);
|
||||
|
||||
template<typename...>
|
||||
static std::false_type test(...);
|
||||
};
|
||||
|
||||
struct has_key_value_pair_impl {
|
||||
template<typename T, typename U = unqualified_t<T>,
|
||||
typename V = typename U::value_type,
|
||||
typename F = decltype(std::declval<V&>().first),
|
||||
typename S = decltype(std::declval<V&>().second)>
|
||||
static std::true_type test(int);
|
||||
|
||||
template<typename...>
|
||||
static std::false_type test(...);
|
||||
};
|
||||
|
||||
template <typename T, typename U = T, typename = decltype(std::declval<T&>() < std::declval<U&>())>
|
||||
std::true_type supports_op_less_test(const T&);
|
||||
std::false_type supports_op_less_test(...);
|
||||
template <typename T, typename U = T, typename = decltype(std::declval<T&>() == std::declval<U&>())>
|
||||
std::true_type supports_op_equal_test(const T&);
|
||||
std::false_type supports_op_equal_test(...);
|
||||
template <typename T, typename U = T, typename = decltype(std::declval<T&>() <= std::declval<U&>())>
|
||||
std::true_type supports_op_less_equal_test(const T&);
|
||||
std::false_type supports_op_less_equal_test(...);
|
||||
|
||||
} // meta_detail
|
||||
|
||||
template <typename T>
|
||||
using supports_op_less = decltype(meta_detail::supports_op_less_test(std::declval<T&>()));
|
||||
template <typename T>
|
||||
using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::declval<T&>()));
|
||||
template <typename T>
|
||||
using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::declval<T&>()));
|
||||
|
||||
template<typename T>
|
||||
struct is_callable : boolean<meta_detail::is_callable<T>::value> {};
|
||||
|
||||
template<typename T>
|
||||
struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test<T>(0)) {};
|
||||
|
||||
template<typename T>
|
||||
struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test<T>(0)) {};
|
||||
|
||||
template <typename T>
|
||||
using is_string_constructible = any<std::is_same<unqualified_t<T>, const char*>, std::is_same<unqualified_t<T>, char>, std::is_same<unqualified_t<T>, std::string>, std::is_same<unqualified_t<T>, std::initializer_list<char>>>;
|
||||
|
||||
template <typename T>
|
||||
using is_c_str = any<
|
||||
std::is_same<std::decay_t<unqualified_t<T>>, const char*>,
|
||||
std::is_same<std::decay_t<unqualified_t<T>>, char*>,
|
||||
std::is_same<unqualified_t<T>, std::string>
|
||||
>;
|
||||
|
||||
template <typename T>
|
||||
struct is_move_only : all<
|
||||
neg<std::is_reference<T>>,
|
||||
neg<std::is_copy_constructible<unqualified_t<T>>>,
|
||||
std::is_move_constructible<unqualified_t<T>>
|
||||
> {};
|
||||
|
||||
template <typename T>
|
||||
using is_not_move_only = neg<is_move_only<T>>;
|
||||
|
||||
namespace meta_detail {
|
||||
template <typename T, meta::disable<meta::is_specialization_of<std::tuple, meta::unqualified_t<T>>> = meta::enabler>
|
||||
decltype(auto) force_tuple(T&& x) {
|
||||
return std::forward_as_tuple(std::forward<T>(x));
|
||||
}
|
||||
|
||||
template <typename T, meta::enable<meta::is_specialization_of<std::tuple, meta::unqualified_t<T>>> = meta::enabler>
|
||||
decltype(auto) force_tuple(T&& x) {
|
||||
return std::forward<T>(x);
|
||||
}
|
||||
} // meta_detail
|
||||
|
||||
template <typename... X>
|
||||
decltype(auto) tuplefy(X&&... x) {
|
||||
return std::tuple_cat(meta_detail::force_tuple(std::forward<X>(x))...);
|
||||
}
|
||||
} // meta
|
||||
namespace detail {
|
||||
template <std::size_t I, typename Tuple>
|
||||
decltype(auto) forward_get(Tuple&& tuple) {
|
||||
return std::forward<meta::tuple_element_t<I, Tuple>>(std::get<I>(tuple));
|
||||
}
|
||||
|
||||
template <std::size_t... I, typename Tuple>
|
||||
auto forward_tuple_impl(std::index_sequence<I...>, Tuple&& tuple) -> decltype(std::tuple<decltype(forward_get<I>(tuple))...>(forward_get<I>(tuple)...)) {
|
||||
return std::tuple<decltype(forward_get<I>(tuple))...>(std::move(std::get<I>(tuple))...);
|
||||
}
|
||||
|
||||
template <typename Tuple>
|
||||
auto forward_tuple(Tuple&& tuple) {
|
||||
auto x = forward_tuple_impl(std::make_index_sequence<std::tuple_size<meta::unqualified_t<Tuple>>::value>(), std::forward<Tuple>(tuple));
|
||||
return x;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto unwrap(T&& item) -> decltype(std::forward<T>(item)) {
|
||||
return std::forward<T>(item);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& unwrap(std::reference_wrapper<T> arg) {
|
||||
return arg.get();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto deref(T&& item) -> decltype(std::forward<T>(item)) {
|
||||
return std::forward<T>(item);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T& deref(T* item) {
|
||||
return *item;
|
||||
}
|
||||
|
||||
template<typename T, typename Dx>
|
||||
inline std::add_lvalue_reference_t<T> deref(std::unique_ptr<T, Dx>& item) {
|
||||
return *item;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::add_lvalue_reference_t<T> deref(std::shared_ptr<T>& item) {
|
||||
return *item;
|
||||
}
|
||||
|
||||
template<typename T, typename Dx>
|
||||
inline std::add_lvalue_reference_t<T> deref(const std::unique_ptr<T, Dx>& item) {
|
||||
return *item;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::add_lvalue_reference_t<T> deref(const std::shared_ptr<T>& item) {
|
||||
return *item;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T* ptr(T& val) {
|
||||
return std::addressof(val);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T* ptr(std::reference_wrapper<T> val) {
|
||||
return std::addressof(val.get());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
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 <type_traits>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
namespace sol {
|
||||
template<std::size_t I>
|
||||
using index_value = std::integral_constant<std::size_t, I>;
|
||||
|
||||
namespace meta {
|
||||
template<typename T>
|
||||
struct identity { typedef T type; };
|
||||
|
||||
template<typename T>
|
||||
using identity_t = typename identity<T>::type;
|
||||
|
||||
template<typename... Args>
|
||||
struct is_tuple : std::false_type { };
|
||||
|
||||
template<typename... Args>
|
||||
struct is_tuple<std::tuple<Args...>> : std::true_type { };
|
||||
|
||||
template <typename T>
|
||||
struct is_builtin_type : std::integral_constant<bool, std::is_arithmetic<T>::value || std::is_pointer<T>::value || std::is_array<T>::value> {};
|
||||
|
||||
template<typename T>
|
||||
struct unwrapped {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct unwrapped<std::reference_wrapper<T>> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using unwrapped_t = typename unwrapped<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct unwrap_unqualified : unwrapped<unqualified_t<T>> {};
|
||||
|
||||
template <typename T>
|
||||
using unwrap_unqualified_t = typename unwrap_unqualified<T>::type;
|
||||
|
||||
template<typename T>
|
||||
struct remove_member_pointer;
|
||||
|
||||
template<typename R, typename T>
|
||||
struct remove_member_pointer<R T::*> {
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename R, typename T>
|
||||
struct remove_member_pointer<R T::* const> {
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using remove_member_pointer_t = remove_member_pointer<T>;
|
||||
|
||||
template<template<typename...> class Templ, typename T>
|
||||
struct is_specialization_of : std::false_type { };
|
||||
template<typename... T, template<typename...> class Templ>
|
||||
struct is_specialization_of<Templ, Templ<T...>> : std::true_type { };
|
||||
|
||||
template<class T, class...>
|
||||
struct all_same : std::true_type { };
|
||||
|
||||
template<class T, class U, class... Args>
|
||||
struct all_same<T, U, Args...> : std::integral_constant <bool, std::is_same<T, U>::value && all_same<T, Args...>::value> { };
|
||||
|
||||
template<class T, class...>
|
||||
struct any_same : std::false_type { };
|
||||
|
||||
template<class T, class U, class... Args>
|
||||
struct any_same<T, U, Args...> : std::integral_constant <bool, std::is_same<T, U>::value || any_same<T, Args...>::value> { };
|
||||
|
||||
template<typename T>
|
||||
using invoke_t = typename T::type;
|
||||
|
||||
template<bool B>
|
||||
using boolean = std::integral_constant<bool, B>;
|
||||
|
||||
template<typename T>
|
||||
using neg = boolean<!T::value>;
|
||||
|
||||
template<typename Condition, typename Then, typename Else>
|
||||
using condition = std::conditional_t<Condition::value, Then, Else>;
|
||||
|
||||
template<typename... Args>
|
||||
struct all : boolean<true> {};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
struct all<T, Args...> : condition<T, all<Args...>, boolean<false>> {};
|
||||
|
||||
template<typename... Args>
|
||||
struct any : boolean<false> {};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
struct any<T, Args...> : condition<T, boolean<true>, any<Args...>> {};
|
||||
|
||||
enum class enable_t {
|
||||
_
|
||||
};
|
||||
|
||||
constexpr const auto enabler = enable_t::_;
|
||||
|
||||
template<bool value, typename T = void>
|
||||
using disable_if_t = std::enable_if_t<!value, T>;
|
||||
|
||||
template<typename... Args>
|
||||
using enable = std::enable_if_t<all<Args...>::value, enable_t>;
|
||||
|
||||
template<typename... Args>
|
||||
using disable = std::enable_if_t<neg<all<Args...>>::value, enable_t>;
|
||||
|
||||
template<typename... Args>
|
||||
using disable_any = std::enable_if_t<neg<any<Args...>>::value, enable_t>;
|
||||
|
||||
template<typename V, typename... Vs>
|
||||
struct find_in_pack_v : boolean<false> { };
|
||||
|
||||
template<typename V, typename Vs1, typename... Vs>
|
||||
struct find_in_pack_v<V, Vs1, Vs...> : any<boolean<(V::value == Vs1::value)>, find_in_pack_v<V, Vs...>> { };
|
||||
|
||||
namespace meta_detail {
|
||||
template<std::size_t I, typename T, typename... Args>
|
||||
struct index_in_pack : std::integral_constant<std::size_t, SIZE_MAX> { };
|
||||
|
||||
template<std::size_t I, typename T, typename T1, typename... Args>
|
||||
struct index_in_pack<I, T, T1, Args...> : std::conditional_t<std::is_same<T, T1>::value, std::integral_constant<std::ptrdiff_t, I>, index_in_pack<I + 1, T, Args...>> { };
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> { };
|
||||
|
||||
template<typename T, typename List>
|
||||
struct index_in : meta_detail::index_in_pack<0, T, List> { };
|
||||
|
||||
template<typename T, typename... Args>
|
||||
struct index_in<T, types<Args...>> : meta_detail::index_in_pack<0, T, Args...> { };
|
||||
|
||||
template<std::size_t I, typename... Args>
|
||||
struct at_in_pack {};
|
||||
|
||||
template<std::size_t I, typename... Args>
|
||||
using at_in_pack_t = typename at_in_pack<I, Args...>::type;
|
||||
|
||||
template<std::size_t I, typename Arg, typename... Args>
|
||||
struct at_in_pack<I, Arg, Args...> : std::conditional<I == 0, Arg, at_in_pack_t<I - 1, Args...>> {};
|
||||
|
||||
template<typename Arg, typename... Args>
|
||||
struct at_in_pack<0, Arg, Args...> { typedef Arg type; };
|
||||
|
||||
namespace meta_detail {
|
||||
template<std::size_t Limit, std::size_t I, template<typename...> class Pred, typename... Ts>
|
||||
struct count_for_pack : std::integral_constant<std::size_t, 0> {};
|
||||
template<std::size_t Limit, std::size_t I, template<typename...> class Pred, typename T, typename... Ts>
|
||||
struct count_for_pack<Limit, I, Pred, T, Ts...> : std::conditional_t < sizeof...(Ts) == 0 || Limit < 2,
|
||||
std::integral_constant<std::size_t, I + static_cast<std::size_t>(Limit != 0 && Pred<T>::value)>,
|
||||
count_for_pack<Limit - 1, I + static_cast<std::size_t>(Pred<T>::value), Pred, Ts...>
|
||||
> { };
|
||||
template<std::size_t I, template<typename...> class Pred, typename... Ts>
|
||||
struct count_2_for_pack : std::integral_constant<std::size_t, 0> {};
|
||||
template<std::size_t I, template<typename...> class Pred, typename T, typename U, typename... Ts>
|
||||
struct count_2_for_pack<I, Pred, T, U, Ts...> : std::conditional_t<sizeof...(Ts) == 0,
|
||||
std::integral_constant<std::size_t, I + static_cast<std::size_t>(Pred<T>::value)>,
|
||||
count_2_for_pack<I + static_cast<std::size_t>(Pred<T>::value), Pred, Ts...>
|
||||
> { };
|
||||
} // meta_detail
|
||||
|
||||
template<template<typename...> class Pred, typename... Ts>
|
||||
struct count_for_pack : meta_detail::count_for_pack<sizeof...(Ts), 0, Pred, Ts...> { };
|
||||
|
||||
template<template<typename...> class Pred, typename List>
|
||||
struct count_for;
|
||||
|
||||
template<template<typename...> class Pred, typename... Args>
|
||||
struct count_for<Pred, types<Args...>> : count_for_pack<Pred, Args...> {};
|
||||
|
||||
template<std::size_t Limit, template<typename...> class Pred, typename... Ts>
|
||||
struct count_for_to_pack : meta_detail::count_for_pack<Limit, 0, Pred, Ts...> { };
|
||||
|
||||
template<template<typename...> class Pred, typename... Ts>
|
||||
struct count_2_for_pack : meta_detail::count_2_for_pack<0, Pred, Ts...> { };
|
||||
|
||||
template<typename... Args>
|
||||
struct return_type {
|
||||
typedef std::tuple<Args...> type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct return_type<T> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct return_type<> {
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
using return_type_t = typename return_type<Args...>::type;
|
||||
|
||||
namespace meta_detail {
|
||||
template <typename> struct always_true : std::true_type {};
|
||||
struct is_invokable_tester {
|
||||
template <typename Fun, typename... Args>
|
||||
always_true<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int);
|
||||
template <typename...>
|
||||
std::false_type static test(...);
|
||||
};
|
||||
} // meta_detail
|
||||
|
||||
template <typename T>
|
||||
struct is_invokable;
|
||||
template <typename Fun, typename... Args>
|
||||
struct is_invokable<Fun(Args...)> : decltype(meta_detail::is_invokable_tester::test<Fun, Args...>(0)) {};
|
||||
|
||||
namespace meta_detail {
|
||||
|
||||
template<typename T, bool isclass = std::is_class<unqualified_t<T>>::value>
|
||||
struct is_callable : std::is_function<std::remove_pointer_t<T>> {};
|
||||
|
||||
template<typename T>
|
||||
struct is_callable<T, true> {
|
||||
using yes = char;
|
||||
using no = struct { char s[2]; };
|
||||
|
||||
struct F { void operator()(); };
|
||||
struct Derived : T, F {};
|
||||
template<typename U, U> struct Check;
|
||||
|
||||
template<typename V>
|
||||
static no test(Check<void (F::*)(), &V::operator()>*);
|
||||
|
||||
template<typename>
|
||||
static yes test(...);
|
||||
|
||||
static const bool value = sizeof(test<Derived>(0)) == sizeof(yes);
|
||||
};
|
||||
|
||||
struct has_begin_end_impl {
|
||||
template<typename T, typename U = unqualified_t<T>,
|
||||
typename B = decltype(std::declval<U&>().begin()),
|
||||
typename E = decltype(std::declval<U&>().end())>
|
||||
static std::true_type test(int);
|
||||
|
||||
template<typename...>
|
||||
static std::false_type test(...);
|
||||
};
|
||||
|
||||
struct has_key_value_pair_impl {
|
||||
template<typename T, typename U = unqualified_t<T>,
|
||||
typename V = typename U::value_type,
|
||||
typename F = decltype(std::declval<V&>().first),
|
||||
typename S = decltype(std::declval<V&>().second)>
|
||||
static std::true_type test(int);
|
||||
|
||||
template<typename...>
|
||||
static std::false_type test(...);
|
||||
};
|
||||
|
||||
template <typename T, typename U = T, typename = decltype(std::declval<T&>() < std::declval<U&>())>
|
||||
std::true_type supports_op_less_test(const T&);
|
||||
std::false_type supports_op_less_test(...);
|
||||
template <typename T, typename U = T, typename = decltype(std::declval<T&>() == std::declval<U&>())>
|
||||
std::true_type supports_op_equal_test(const T&);
|
||||
std::false_type supports_op_equal_test(...);
|
||||
template <typename T, typename U = T, typename = decltype(std::declval<T&>() <= std::declval<U&>())>
|
||||
std::true_type supports_op_less_equal_test(const T&);
|
||||
std::false_type supports_op_less_equal_test(...);
|
||||
|
||||
} // meta_detail
|
||||
|
||||
template <typename T>
|
||||
using supports_op_less = decltype(meta_detail::supports_op_less_test(std::declval<T&>()));
|
||||
template <typename T>
|
||||
using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::declval<T&>()));
|
||||
template <typename T>
|
||||
using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::declval<T&>()));
|
||||
|
||||
template<typename T>
|
||||
struct is_callable : boolean<meta_detail::is_callable<T>::value> {};
|
||||
|
||||
template<typename T>
|
||||
struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test<T>(0)) {};
|
||||
|
||||
template<typename T>
|
||||
struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test<T>(0)) {};
|
||||
|
||||
template <typename T>
|
||||
using is_string_constructible = any<std::is_same<unqualified_t<T>, const char*>, std::is_same<unqualified_t<T>, char>, std::is_same<unqualified_t<T>, std::string>, std::is_same<unqualified_t<T>, std::initializer_list<char>>>;
|
||||
|
||||
template <typename T>
|
||||
using is_c_str = any<
|
||||
std::is_same<std::decay_t<unqualified_t<T>>, const char*>,
|
||||
std::is_same<std::decay_t<unqualified_t<T>>, char*>,
|
||||
std::is_same<unqualified_t<T>, std::string>
|
||||
>;
|
||||
|
||||
template <typename T>
|
||||
struct is_move_only : all<
|
||||
neg<std::is_reference<T>>,
|
||||
neg<std::is_copy_constructible<unqualified_t<T>>>,
|
||||
std::is_move_constructible<unqualified_t<T>>
|
||||
> {};
|
||||
|
||||
template <typename T>
|
||||
using is_not_move_only = neg<is_move_only<T>>;
|
||||
|
||||
namespace meta_detail {
|
||||
template <typename T, meta::disable<meta::is_specialization_of<std::tuple, meta::unqualified_t<T>>> = meta::enabler>
|
||||
decltype(auto) force_tuple(T&& x) {
|
||||
return std::forward_as_tuple(std::forward<T>(x));
|
||||
}
|
||||
|
||||
template <typename T, meta::enable<meta::is_specialization_of<std::tuple, meta::unqualified_t<T>>> = meta::enabler>
|
||||
decltype(auto) force_tuple(T&& x) {
|
||||
return std::forward<T>(x);
|
||||
}
|
||||
} // meta_detail
|
||||
|
||||
template <typename... X>
|
||||
decltype(auto) tuplefy(X&&... x) {
|
||||
return std::tuple_cat(meta_detail::force_tuple(std::forward<X>(x))...);
|
||||
}
|
||||
} // meta
|
||||
namespace detail {
|
||||
template <std::size_t I, typename Tuple>
|
||||
decltype(auto) forward_get(Tuple&& tuple) {
|
||||
return std::forward<meta::tuple_element_t<I, Tuple>>(std::get<I>(tuple));
|
||||
}
|
||||
|
||||
template <std::size_t... I, typename Tuple>
|
||||
auto forward_tuple_impl(std::index_sequence<I...>, Tuple&& tuple) -> decltype(std::tuple<decltype(forward_get<I>(tuple))...>(forward_get<I>(tuple)...)) {
|
||||
return std::tuple<decltype(forward_get<I>(tuple))...>(std::move(std::get<I>(tuple))...);
|
||||
}
|
||||
|
||||
template <typename Tuple>
|
||||
auto forward_tuple(Tuple&& tuple) {
|
||||
auto x = forward_tuple_impl(std::make_index_sequence<std::tuple_size<meta::unqualified_t<Tuple>>::value>(), std::forward<Tuple>(tuple));
|
||||
return x;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto unwrap(T&& item) -> decltype(std::forward<T>(item)) {
|
||||
return std::forward<T>(item);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& unwrap(std::reference_wrapper<T> arg) {
|
||||
return arg.get();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto deref(T&& item) -> decltype(std::forward<T>(item)) {
|
||||
return std::forward<T>(item);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T& deref(T* item) {
|
||||
return *item;
|
||||
}
|
||||
|
||||
template<typename T, typename Dx>
|
||||
inline std::add_lvalue_reference_t<T> deref(std::unique_ptr<T, Dx>& item) {
|
||||
return *item;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::add_lvalue_reference_t<T> deref(std::shared_ptr<T>& item) {
|
||||
return *item;
|
||||
}
|
||||
|
||||
template<typename T, typename Dx>
|
||||
inline std::add_lvalue_reference_t<T> deref(const std::unique_ptr<T, Dx>& item) {
|
||||
return *item;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::add_lvalue_reference_t<T> deref(const std::shared_ptr<T>& item) {
|
||||
return *item;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T* ptr(T& val) {
|
||||
return std::addressof(val);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T* ptr(std::reference_wrapper<T> val) {
|
||||
return std::addressof(val.get());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T* ptr(T* val) {
|
||||
return val;
|
||||
}
|
||||
} // detail
|
||||
} // sol
|
||||
|
||||
#endif // SOL_TRAITS_HPP
|
||||
|
|
|
@ -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>("B",
|
||||
sol::default_constructor,
|
||||
"thing", &B::thing,
|
||||
"var", &B::var
|
||||
);
|
||||
|
||||
lua.script(R"(
|
||||
b = B.new()
|
||||
print(b.var)
|
||||
b:thing()
|
||||
)");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user