mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
This mega-commit implements the new usertype_metatable
while keeping everything else still intact. Blurgh, managing API versions suck...
This commit is contained in:
parent
9b65fb9f93
commit
e35fe6be85
2
Optional
2
Optional
|
@ -1 +1 @@
|
|||
Subproject commit e62740b328e100ac76821e151cb3cfe7412bd98a
|
||||
Subproject commit f11b4f00eb029862dd2a4d7e3497324aba8a020f
|
218
sol/bind_traits.hpp
Normal file
218
sol/bind_traits.hpp
Normal file
|
@ -0,0 +1,218 @@
|
|||
#pragma once
|
||||
|
||||
#include "tuple.hpp"
|
||||
|
||||
namespace sol {
|
||||
namespace meta {
|
||||
namespace meta_detail {
|
||||
|
||||
template<class F>
|
||||
struct check_deducible_signature {
|
||||
struct nat {};
|
||||
template<class G>
|
||||
static auto test(int) -> decltype(&G::operator(), void());
|
||||
template<class>
|
||||
static auto test(...) -> nat;
|
||||
|
||||
using type = std::is_void<decltype(test<F>(0))>;
|
||||
};
|
||||
} // meta_detail
|
||||
|
||||
template<class F>
|
||||
struct has_deducible_signature : meta_detail::check_deducible_signature<F>::type { };
|
||||
|
||||
namespace meta_detail {
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
struct void_tuple_element : meta::tuple_element<I, T> {};
|
||||
|
||||
template <std::size_t I>
|
||||
struct void_tuple_element<I, std::tuple<>> { typedef void type; };
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
using void_tuple_element_t = typename void_tuple_element<I, T>::type;
|
||||
|
||||
template <bool has_c_variadic, typename T, typename R, typename... Args>
|
||||
struct basic_traits {
|
||||
private:
|
||||
typedef std::conditional_t<std::is_void<T>::value, int, T>& first_type;
|
||||
|
||||
public:
|
||||
static const bool is_member_function = std::is_void<T>::value;
|
||||
static const bool has_c_var_arg = has_c_variadic;
|
||||
static const std::size_t arity = sizeof...(Args);
|
||||
static const std::size_t free_arity = sizeof...(Args) + static_cast<std::size_t>(!std::is_void<T>::value);
|
||||
typedef types<Args...> args_list;
|
||||
typedef std::tuple<Args...> args_tuple;
|
||||
typedef T object_type;
|
||||
typedef R return_type;
|
||||
typedef tuple_types<R> returns_list;
|
||||
typedef R(function_type)(Args...);
|
||||
typedef std::conditional_t<std::is_void<T>::value, args_list, types<first_type, Args...>> free_args_list;
|
||||
typedef std::conditional_t<std::is_void<T>::value, R(Args...), R(first_type, Args...)> free_function_type;
|
||||
typedef std::conditional_t<std::is_void<T>::value, R(*)(Args...), R(*)(first_type, Args...)> free_function_pointer_type;
|
||||
typedef std::remove_pointer_t<free_function_pointer_type> signature_type;
|
||||
template<std::size_t i>
|
||||
using arg_at = void_tuple_element_t<i, args_tuple>;
|
||||
};
|
||||
|
||||
template<typename Signature, bool b = has_deducible_signature<Signature>::value>
|
||||
struct fx_traits : basic_traits<false, void, void> {};
|
||||
|
||||
// Free Functions
|
||||
template<typename R, typename... Args>
|
||||
struct fx_traits<R(Args...), false> : basic_traits<false, void, R, Args...> {
|
||||
typedef R(*function_pointer_type)(Args...);
|
||||
};
|
||||
|
||||
template<typename R, typename... Args>
|
||||
struct fx_traits<R(*)(Args...), false> : basic_traits<false, void, R, Args...> {
|
||||
typedef R(*function_pointer_type)(Args...);
|
||||
};
|
||||
|
||||
template<typename R, typename... Args>
|
||||
struct fx_traits<R(Args..., ...), false> : basic_traits<true, void, R, Args...> {
|
||||
typedef R(*function_pointer_type)(Args..., ...);
|
||||
};
|
||||
|
||||
template<typename R, typename... Args>
|
||||
struct fx_traits<R(*)(Args..., ...), false> : basic_traits<true, void, R, Args...> {
|
||||
typedef R(*function_pointer_type)(Args..., ...);
|
||||
};
|
||||
|
||||
// Member Functions
|
||||
/* C-Style Variadics */
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...), false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...);
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...), false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...);
|
||||
};
|
||||
|
||||
/* Const Volatile */
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const volatile, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const volatile;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const volatile, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const volatile;
|
||||
};
|
||||
|
||||
/* Member Function Qualifiers */
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) &, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) &;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) &, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) &;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const &, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const &;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const &, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const &;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const volatile &, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const volatile &;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const volatile &, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const volatile &;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) &&, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) &&;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) &&, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) &&;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const &&, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const &&;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const &&, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const &&;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const volatile &&, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const volatile &&;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const volatile &&, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&;
|
||||
};
|
||||
|
||||
template<typename Signature>
|
||||
struct fx_traits<Signature, true> : fx_traits<typename fx_traits<decltype(&Signature::operator())>::function_type, false> {};
|
||||
|
||||
template<typename Signature, bool b = std::is_member_object_pointer<Signature>::value>
|
||||
struct callable_traits : fx_traits<std::decay_t<Signature>> {
|
||||
|
||||
};
|
||||
|
||||
template<typename R, typename T>
|
||||
struct callable_traits<R(T::*), true> {
|
||||
typedef R Arg;
|
||||
typedef T object_type;
|
||||
using signature_type = R(T::*);
|
||||
static const bool is_member_function = false;
|
||||
static const std::size_t arity = 1;
|
||||
static const std::size_t free_arity = 2;
|
||||
typedef std::tuple<Arg> args_tuple;
|
||||
typedef R return_type;
|
||||
typedef types<Arg> args_list;
|
||||
typedef meta::tuple_types<R> returns_list;
|
||||
typedef R(function_type)(T&, R);
|
||||
typedef R(*function_pointer_type)(T&, R);
|
||||
typedef R(*free_function_pointer_type)(T&, R);
|
||||
template<std::size_t i>
|
||||
using arg_at = void_tuple_element_t<i, args_tuple>;
|
||||
};
|
||||
} // meta_detail
|
||||
|
||||
template<typename Signature>
|
||||
struct bind_traits : meta_detail::callable_traits<Signature> {};
|
||||
|
||||
template<typename Signature>
|
||||
using function_args_t = typename bind_traits<Signature>::args_list;
|
||||
|
||||
template<typename Signature>
|
||||
using function_signature_t = typename bind_traits<Signature>::signature_type;
|
||||
|
||||
template<typename Signature>
|
||||
using function_return_t = typename bind_traits<Signature>::return_type;
|
||||
|
||||
} // meta
|
||||
} // sol
|
282
sol/call.hpp
Normal file
282
sol/call.hpp
Normal file
|
@ -0,0 +1,282 @@
|
|||
// The MIT License (MIT)
|
||||
|
||||
// Copyright (c) 2013-2016 Rappt1101010z, 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_CALL_HPP
|
||||
#define SOL_CALL_HPP
|
||||
|
||||
#include "wrapper.hpp"
|
||||
#include "property.hpp"
|
||||
#include "stack.hpp"
|
||||
|
||||
namespace sol {
|
||||
namespace call_detail {
|
||||
|
||||
template <bool b, typename F>
|
||||
inline decltype(auto) pick(std::integral_constant<bool, b>, F&& f) {
|
||||
return std::forward<F>(f);
|
||||
}
|
||||
|
||||
template <typename R, typename W>
|
||||
inline auto& pick(std::true_type, property_wrapper<R, W>& f) {
|
||||
return f.read;
|
||||
}
|
||||
|
||||
template <typename R, typename W>
|
||||
inline auto& pick(std::false_type, property_wrapper<R, W>& f) {
|
||||
return f.write;
|
||||
}
|
||||
|
||||
namespace overload_detail {
|
||||
template <std::size_t... M, typename Match, typename... Args>
|
||||
inline int overload_match_arity(sol::types<>, std::index_sequence<>, std::index_sequence<M...>, Match&&, lua_State* L, int, int, Args&&...) {
|
||||
return luaL_error(L, "sol: no matching function call takes this number of arguments and the specified types");
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Fxs, std::size_t I, std::size_t... In, std::size_t... M, typename Match, typename... Args>
|
||||
inline int overload_match_arity(sol::types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
|
||||
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits;
|
||||
typedef meta::tuple_types<typename traits::return_type> return_types;
|
||||
typedef typename traits::free_args_list args_list;
|
||||
typedef typename args_list::indices args_indices;
|
||||
int farity = traits::free_arity;
|
||||
// compile-time eliminate any functions that we know ahead of time are of improper arity
|
||||
if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) {
|
||||
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
if (traits::free_arity != fxarity) {
|
||||
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<traits::arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
if (!stack::stack_detail::check_types<true>().check(args_list(), args_indices(), L, start, no_panic)) {
|
||||
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
} // overload_detail
|
||||
|
||||
template <typename... Functions, typename Match, typename... Args>
|
||||
inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
|
||||
return overload_detail::overload_match_arity(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Functions, typename Match, typename... Args>
|
||||
inline int overload_match(Match&& matchfx, lua_State* L, int start, Args&&... args) {
|
||||
int fxarity = lua_gettop(L) - (start - 1);
|
||||
return overload_match_arity<Functions...>(std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename F, bool is_index, bool is_variable, typename = void>
|
||||
struct agnostic_lua_call_wrapper {
|
||||
static int var_call(std::true_type, lua_State* L, F f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
typedef typename wrap::free_args_list args_list;
|
||||
return stack::call_into_lua<is_index ? 1 : 2>(returns_list(), args_list(), L, is_index ? 2 : 3, wrap::caller(), f);
|
||||
}
|
||||
|
||||
static int var_call(std::false_type, lua_State* L, F f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::free_args_list args_list;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
return stack::call_into_lua(returns_list(), args_list(), L, 1, wrap::caller(), f);
|
||||
}
|
||||
|
||||
static int call(lua_State* L, F f) {
|
||||
return var_call(std::integral_constant<bool, is_variable>(), L, f);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, bool is_index, bool is_variable>
|
||||
struct agnostic_lua_call_wrapper<F, is_index, is_variable, std::enable_if_t<std::is_member_function_pointer<F>::value>> {
|
||||
static int call(lua_State* L, F f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
typedef typename wrap::args_list args_list;
|
||||
#ifdef SOL_SAFE_USERTYPE
|
||||
typedef typename wrap::object_type object_type;
|
||||
object_type* o = stack::get<object_type*>(L, 1);
|
||||
if (o == nullptr) {
|
||||
return luaL_error(L, "sol: received null for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)");
|
||||
}
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), args_list(), L, is_variable ? 3 : 2, wrap::caller(), f, *o);
|
||||
#else
|
||||
object_type& o = stack::get<object_type&>(L, 1);
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), args_list(), L, is_variable ? 3 : 2, wrap::caller(), f);
|
||||
#endif // Safety
|
||||
}
|
||||
};
|
||||
|
||||
template <bool is_index, bool is_variable, typename C>
|
||||
struct agnostic_lua_call_wrapper<no_prop, is_index, is_variable, C> {
|
||||
static int call(lua_State* L, no_prop) {
|
||||
return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property");
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, bool is_variable>
|
||||
struct agnostic_lua_call_wrapper<F, false, is_variable, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
|
||||
typedef sol::lua_bind_traits<F> traits_type;
|
||||
|
||||
static int call_assign(std::true_type, lua_State* L, F f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::args_list args_list;
|
||||
typedef typename wrap::object_type object_type;
|
||||
#ifdef SOL_SAFE_USERTYPE
|
||||
object_type* o = stack::get<object_type*>(L, 1);
|
||||
if (o == nullptr) {
|
||||
if (is_variable) {
|
||||
return luaL_error(L, "sol: received null for 'self' argument (bad '.' access?)");
|
||||
}
|
||||
return luaL_error(L, "sol: received null for 'self' argument (pass 'self' as first argument)");
|
||||
}
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, wrap::caller(), f, *o);
|
||||
#else
|
||||
object_type& o = stack::get<object_type&>(L, 1);
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, wrap::caller(), f, o);
|
||||
#endif // Safety
|
||||
}
|
||||
|
||||
static int call_assign(std::false_type, lua_State* L, F f) {
|
||||
return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available");
|
||||
}
|
||||
|
||||
static int call_const(std::false_type, lua_State* L, F f) {
|
||||
typedef typename traits_type::return_type R;
|
||||
return call_assign(std::is_assignable<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>(), L, f);
|
||||
}
|
||||
|
||||
static int call_const(std::true_type, lua_State* L, F f) {
|
||||
return luaL_error(L, "sol: cannot write to a readonly (const) variable");
|
||||
}
|
||||
|
||||
static int call(lua_State* L, F f) {
|
||||
return call_const(std::is_const<typename traits_type::return_type>(), L, f);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, bool is_variable>
|
||||
struct agnostic_lua_call_wrapper<F, true, is_variable, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
|
||||
typedef sol::lua_bind_traits<F> traits_type;
|
||||
|
||||
static int call(lua_State* L, F f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::object_type object_type;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
#ifdef SOL_SAFE_USERTYPE
|
||||
object_type* o = stack::get<object_type*>(L, 1);
|
||||
if (o == nullptr) {
|
||||
if (is_variable) {
|
||||
return luaL_error(L, "sol: 'self' argument is nullptr (bad '.' access?)");
|
||||
}
|
||||
return luaL_error(L, "sol: 'self' argument is nullptr (pass 'self' as first argument)");
|
||||
}
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), types<>(), L, is_variable ? 3 : 2, wrap::caller(), f, *o);
|
||||
#else
|
||||
object_type& o = stack::get<object_type&>(L, 1);
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), types<>(), L, is_variable ? 3 : 2, wrap::caller(), f, o);
|
||||
#endif // Safety
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Fs, bool is_index, bool is_variable, typename C>
|
||||
struct agnostic_lua_call_wrapper<sol::overload_set<Fs...>, is_index, is_variable, C> {
|
||||
typedef sol::overload_set<Fs...> F;
|
||||
|
||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
static int select_call(sol::types<Fx>, sol::index_value<I>, sol::types<R...> r, sol::types<Args...> a, lua_State* L, int, int start, F& fx) {
|
||||
auto& f = std::get<I>(fx.set);
|
||||
return agnostic_lua_call_wrapper<Fx, is_index, is_variable>{}.call(L, f);
|
||||
}
|
||||
|
||||
static int call(lua_State* L, F& fx) {
|
||||
auto mfx = [&](auto&&... args) { return select_call(std::forward<decltype(args)>(args)...); };
|
||||
return overload_match_arity<Fs...>(mfx, L, lua_gettop(L), 1, fx);
|
||||
}
|
||||
};
|
||||
|
||||
template <bool is_index, bool is_variable, typename C>
|
||||
struct agnostic_lua_call_wrapper<sol::no_construction, is_index, is_variable, C> {
|
||||
static int call(lua_State* L, sol::no_construction&) {
|
||||
return luaL_error(L, "cannot call something tagged with 'no construction'");
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename F, bool is_index, bool is_variable, typename = void>
|
||||
struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable> {};
|
||||
|
||||
template <typename T, typename... Args, bool is_index, bool is_variable, typename C>
|
||||
struct lua_call_wrapper<T, sol::constructor_list<Args...>, is_index, is_variable, C> {
|
||||
typedef sol::constructor_list<Args...> F;
|
||||
|
||||
static int call(lua_State* L, F&) {
|
||||
static const auto& meta = usertype_traits<T>::metatable;
|
||||
int argcount = lua_gettop(L);
|
||||
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, meta, 1) : call_syntax::dot;
|
||||
argcount -= static_cast<int>(syntax);
|
||||
|
||||
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||
T*& referencepointer = *pointerpointer;
|
||||
T* obj = reinterpret_cast<T*>(pointerpointer + 1);
|
||||
referencepointer = obj;
|
||||
reference userdataref(L, -1);
|
||||
userdataref.pop();
|
||||
|
||||
function_detail::construct<T, Args...>(detail::constructor_match<T>(obj), L, argcount, 1 + static_cast<int>(syntax));
|
||||
|
||||
userdataref.push();
|
||||
luaL_getmetatable(L, &meta[0]);
|
||||
if (stack::get<type>(L) == type::nil) {
|
||||
lua_pop(L, 1);
|
||||
return luaL_error(L, "sol: unable to get usertype metatable");
|
||||
}
|
||||
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, bool is_index, bool is_variable, typename Fx>
|
||||
int call_wrapped(lua_State* L, Fx&& fx) {
|
||||
return lua_call_wrapper<T, meta::unqualified_t<Fx>, is_index, is_variable>{}.call(L, std::forward<Fx>(fx));
|
||||
}
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct is_var_bind : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct is_var_bind<T, std::enable_if_t<std::is_member_object_pointer<T>::value>> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct is_var_bind<no_prop> : std::true_type {};
|
||||
|
||||
template <typename R, typename W>
|
||||
struct is_var_bind<property_wrapper<R, W>> : std::true_type {};
|
||||
|
||||
} // call_detail
|
||||
|
||||
template <typename T>
|
||||
struct is_variable_binding : call_detail::is_var_bind<meta::unqualified_t<T>> {};
|
||||
|
||||
template <typename T>
|
||||
struct is_function_binding : meta::neg<is_variable_binding<T>> {};
|
||||
|
||||
} // sol
|
||||
|
||||
#endif // SOL_CALL_HPP
|
|
@ -59,7 +59,7 @@ private:
|
|||
|
||||
protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) {
|
||||
int stacksize = lua_gettop( lua_state() );
|
||||
int firstreturn = std::max( 1, stacksize - static_cast<int>( n ) );
|
||||
int firstreturn = (std::max)( 1, stacksize - static_cast<int>( n ) );
|
||||
luacall(n, LUA_MULTRET);
|
||||
int poststacksize = lua_gettop(lua_state());
|
||||
int returncount = poststacksize - (firstreturn - 1);
|
||||
|
|
|
@ -57,7 +57,7 @@ private:
|
|||
|
||||
function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n ) const {
|
||||
int stacksize = lua_gettop( base_t::lua_state( ) );
|
||||
int firstreturn = std::max( 1, stacksize - static_cast<int>( n ) );
|
||||
int firstreturn = (std::max)( 1, stacksize - static_cast<int>( n ) );
|
||||
luacall(n, LUA_MULTRET);
|
||||
int poststacksize = lua_gettop( base_t::lua_state( ) );
|
||||
int returncount = poststacksize - (firstreturn - 1);
|
||||
|
@ -100,7 +100,7 @@ namespace stack {
|
|||
template<typename Signature>
|
||||
struct getter<std::function<Signature>> {
|
||||
typedef meta::bind_traits<Signature> fx_t;
|
||||
typedef typename fx_t::args_type args_types;
|
||||
typedef typename fx_t::args_list args_lists;
|
||||
typedef meta::tuple_types<typename fx_t::return_type> return_types;
|
||||
|
||||
template<typename... Args, typename... Ret>
|
||||
|
@ -127,7 +127,7 @@ struct getter<std::function<Signature>> {
|
|||
}
|
||||
|
||||
static std::function<Signature> get(lua_State* L, int index) {
|
||||
return get_std_func(return_types(), args_types(), L, index);
|
||||
return get_std_func(return_types(), args_lists(), L, index);
|
||||
}
|
||||
};
|
||||
} // stack
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "function_types_overload.hpp"
|
||||
#include "function_types_allocator.hpp"
|
||||
#include "resolve.hpp"
|
||||
#include "call.hpp"
|
||||
|
||||
namespace sol {
|
||||
template <typename Sig, typename... Ps>
|
||||
|
@ -45,13 +46,6 @@ function_arguments<Sig, Args...> function_args( Args&&... args ) {
|
|||
return function_arguments<Sig, Args...>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Allow someone to make a member variable readonly (const)
|
||||
template <typename R, typename T>
|
||||
auto readonly( R T::* v ) {
|
||||
typedef const R C;
|
||||
return static_cast<C T::*>( v );
|
||||
}
|
||||
|
||||
namespace stack {
|
||||
template<typename... Sigs>
|
||||
struct pusher<function_sig<Sigs...>> {
|
||||
|
|
|
@ -34,7 +34,7 @@ struct upvalue_free_function {
|
|||
static int real_call(lua_State* L) {
|
||||
auto udata = stack::stack_detail::get_as_upvalues<function_type*>(L);
|
||||
function_type* fx = udata.first;
|
||||
int r = stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_type(), L, 1, fx);
|
||||
int r = stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_list(), L, 1, fx);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ struct upvalue_member_function {
|
|||
auto fx = [&item, &memfx](auto&&... args) -> typename traits_type::return_type {
|
||||
return (item.*memfx)(std::forward<decltype(args)>(args)...);
|
||||
};
|
||||
return stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_type(), L, 1, fx);
|
||||
return stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_list(), L, 1, fx);
|
||||
}
|
||||
|
||||
static int call (lua_State* L) {
|
||||
|
@ -151,7 +151,7 @@ struct upvalue_this_member_function {
|
|||
auto& item = stack::get<T>(L, 1);
|
||||
return (item.*memfx)(std::forward<decltype(args)>(args)...);
|
||||
};
|
||||
int n = stack::call_into_lua<1>(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_type(), L, 2, fx);
|
||||
int n = stack::call_into_lua<1>(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_list(), L, 2, fx);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,13 @@
|
|||
#define SOL_FUNCTION_TYPES_CORE_HPP
|
||||
|
||||
#include "stack.hpp"
|
||||
#include "wrapper.hpp"
|
||||
#include <memory>
|
||||
|
||||
namespace sol {
|
||||
namespace detail {
|
||||
struct empty {};
|
||||
}
|
||||
template <typename RSig = void, typename WSig = void>
|
||||
struct member_property {
|
||||
typedef std::conditional_t<std::is_void<RSig>::value, detail::empty, RSig> R;
|
||||
|
@ -150,7 +154,7 @@ inline decltype(auto) cleanup_key() {
|
|||
template<typename T, typename Func, typename = void>
|
||||
struct functor {
|
||||
typedef meta::bind_traits<Func> traits_type;
|
||||
typedef typename traits_type::args_type args_type;
|
||||
typedef typename traits_type::args_list args_list;
|
||||
typedef typename traits_type::return_type return_type;
|
||||
typedef std::conditional_t<std::is_pointer<Func>::value || std::is_class<Func>::value, Func, std::add_pointer_t<Func>> function_type;
|
||||
static const std::size_t arity = traits_type::arity;
|
||||
|
@ -179,7 +183,7 @@ struct functor {
|
|||
template<typename T, typename Func>
|
||||
struct functor<T, Func, std::enable_if_t<!std::is_member_pointer<Func>::value && std::is_base_of<T, meta::unqualified_t<typename meta::bind_traits<Func>::template arg_at<0>>>::value>> {
|
||||
typedef meta::bind_traits<Func> traits_type;
|
||||
typedef meta::pop_front_type_t<typename traits_type::args_type> args_type;
|
||||
typedef meta::pop_front_type_t<typename traits_type::args_list> args_list;
|
||||
typedef typename traits_type::return_type return_type;
|
||||
typedef std::conditional_t<std::is_pointer<Func>::value || std::is_class<Func>::value, Func, std::add_pointer_t<Func>> function_type;
|
||||
static const std::size_t arity = traits_type::arity - 1;
|
||||
|
@ -211,7 +215,7 @@ struct functor<T, Func, std::enable_if_t<!std::is_member_pointer<Func>::value &&
|
|||
template<typename T, typename RSig, typename WSig, typename C>
|
||||
struct functor<T, member_property<RSig, WSig>, C> {
|
||||
typedef meta::bind_traits<std::conditional_t<std::is_void<WSig>::value, RSig, WSig>> traits_type;
|
||||
typedef meta::pop_front_type_t<typename traits_type::args_type> args_type;
|
||||
typedef meta::pop_front_type_t<typename traits_type::args_list> args_list;
|
||||
typedef std::conditional_t<std::is_void<typename traits_type::return_type>::value, typename traits_type::template arg_at<0>, typename traits_type::return_type> return_type;
|
||||
typedef member_property<RSig, WSig> function_type;
|
||||
typedef meta::neg<std::is_void<RSig>> can_read;
|
||||
|
@ -244,7 +248,7 @@ struct functor<T, member_property<RSig, WSig>, C> {
|
|||
template<typename T, typename Func>
|
||||
struct functor<T, Func, std::enable_if_t<std::is_member_object_pointer<Func>::value>> {
|
||||
typedef meta::bind_traits<Func> traits_type;
|
||||
typedef typename traits_type::args_type args_type;
|
||||
typedef typename traits_type::args_list args_list;
|
||||
typedef typename traits_type::return_type return_type;
|
||||
static const std::size_t arity = traits_type::arity;
|
||||
typedef std::true_type can_read;
|
||||
|
@ -277,7 +281,7 @@ struct functor<T, Func, std::enable_if_t<std::is_member_object_pointer<Func>::va
|
|||
template<typename T, typename Func>
|
||||
struct functor<T, Func, std::enable_if_t<std::is_member_function_pointer<Func>::value>> {
|
||||
typedef meta::bind_traits<Func> traits_type;
|
||||
typedef typename traits_type::args_type args_type;
|
||||
typedef typename traits_type::args_list args_list;
|
||||
typedef typename traits_type::return_type return_type;
|
||||
static const std::size_t arity = traits_type::arity;
|
||||
static const bool is_free = false;
|
||||
|
|
|
@ -30,14 +30,14 @@ template<typename Func>
|
|||
struct free_function : public base_function {
|
||||
typedef meta::unwrapped_t<meta::unqualified_t<Func>> Function;
|
||||
typedef meta::function_return_t<Function> return_type;
|
||||
typedef meta::function_args_t<Function> args_types;
|
||||
typedef meta::function_args_t<Function> args_lists;
|
||||
Function fx;
|
||||
|
||||
template<typename... Args>
|
||||
free_function(Args&&... args): fx(std::forward<Args>(args)...) {}
|
||||
|
||||
int call(lua_State* L) {
|
||||
return stack::call_into_lua(meta::tuple_types<return_type>(), args_types(), L, 1, fx);
|
||||
return stack::call_into_lua(meta::tuple_types<return_type>(), args_lists(), L, 1, fx);
|
||||
}
|
||||
|
||||
virtual int operator()(lua_State* L) override {
|
||||
|
@ -51,14 +51,14 @@ struct functor_function : public base_function {
|
|||
typedef meta::unwrapped_t<meta::unqualified_t<Func>> Function;
|
||||
typedef decltype(&Function::operator()) function_type;
|
||||
typedef meta::function_return_t<function_type> return_type;
|
||||
typedef meta::function_args_t<function_type> args_types;
|
||||
typedef meta::function_args_t<function_type> args_lists;
|
||||
Function fx;
|
||||
|
||||
template<typename... Args>
|
||||
functor_function(Args&&... args): fx(std::forward<Args>(args)...) {}
|
||||
|
||||
int call(lua_State* L) {
|
||||
return stack::call_into_lua(meta::tuple_types<return_type>(), args_types(), L, 1, fx);
|
||||
return stack::call_into_lua(meta::tuple_types<return_type>(), args_lists(), L, 1, fx);
|
||||
}
|
||||
|
||||
virtual int operator()(lua_State* L) override {
|
||||
|
@ -71,7 +71,7 @@ template<typename T, typename Function>
|
|||
struct member_function : public base_function {
|
||||
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
||||
typedef meta::function_return_t<function_type> return_type;
|
||||
typedef meta::function_args_t<function_type> args_types;
|
||||
typedef meta::function_args_t<function_type> args_lists;
|
||||
struct functor {
|
||||
function_type invocation;
|
||||
T member;
|
||||
|
@ -90,7 +90,7 @@ struct member_function : public base_function {
|
|||
member_function(F&& f, Args&&... args) : fx(std::forward<F>(f), std::forward<Args>(args)...) {}
|
||||
|
||||
int call(lua_State* L) {
|
||||
return stack::call_into_lua(meta::tuple_types<return_type>(), args_types(), L, 1, fx);
|
||||
return stack::call_into_lua(meta::tuple_types<return_type>(), args_lists(), L, 1, fx);
|
||||
}
|
||||
|
||||
virtual int operator()(lua_State* L) override {
|
||||
|
@ -103,7 +103,7 @@ template<typename T, typename Function>
|
|||
struct member_variable : public base_function {
|
||||
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
||||
typedef typename meta::bind_traits<function_type>::return_type return_type;
|
||||
typedef typename meta::bind_traits<function_type>::args_type args_types;
|
||||
typedef typename meta::bind_traits<function_type>::args_list args_lists;
|
||||
function_type var;
|
||||
T member;
|
||||
typedef std::add_lvalue_reference_t<meta::unwrapped_t<std::remove_reference_t<decltype(detail::deref(member))>>> M;
|
||||
|
|
|
@ -36,7 +36,7 @@ struct overload_traits : lua_bind_traits<T> {
|
|||
|
||||
template <typename T, typename Func, typename X>
|
||||
struct overload_traits<functor<T, Func, X>> {
|
||||
typedef typename functor<T, Func, X>::args_type args_type;
|
||||
typedef typename functor<T, Func, X>::args_list args_list;
|
||||
typedef typename functor<T, Func, X>::return_type return_type;
|
||||
static const std::size_t arity = functor<T, Func, X>::arity;
|
||||
static const std::size_t boost = static_cast<std::size_t>(functor<T, Func, X>::is_free);
|
||||
|
@ -51,8 +51,8 @@ template <typename Fx, typename... Fxs, std::size_t I, std::size_t... In, std::s
|
|||
inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int nfxarity, int start, Args&&... args) {
|
||||
typedef overload_traits<meta::unqualified_t<Fx>> traits;
|
||||
typedef meta::tuple_types<typename traits::return_type> return_types;
|
||||
typedef typename traits::args_type args_type;
|
||||
typedef typename args_type::indices args_indices;
|
||||
typedef typename traits::args_list args_list;
|
||||
typedef typename args_list::indices args_indices;
|
||||
int fxarity = traits::boost + nfxarity;
|
||||
// compile-time eliminate any functions that we know ahead of time are of improper arity
|
||||
if (meta::find_in_pack_v<index_value<traits::arity>, index_value<M>...>::value) {
|
||||
|
@ -61,10 +61,10 @@ inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>
|
|||
if (traits::arity != fxarity) {
|
||||
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<traits::arity, M...>(), std::forward<Match>(matchfx), L, nfxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
if (!stack::stack_detail::check_types<true>().check(args_type(), args_indices(), L, start - traits::boost, no_panic)) {
|
||||
if (!stack::stack_detail::check_types<true>().check(args_list(), args_indices(), L, start - traits::boost, no_panic)) {
|
||||
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, nfxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_type(), L, fxarity, start, std::forward<Args>(args)...);
|
||||
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
} // internals
|
||||
|
||||
|
|
|
@ -29,9 +29,9 @@ namespace function_detail {
|
|||
template <typename F, F fx>
|
||||
inline int call_wrapper_variable(std::false_type, lua_State* L) {
|
||||
typedef meta::bind_traits<meta::unqualified_t<F>> traits_type;
|
||||
typedef typename traits_type::args_type args_type;
|
||||
typedef typename traits_type::args_list args_list;
|
||||
typedef meta::tuple_types<typename traits_type::return_type> return_type;
|
||||
return stack::call_into_lua(return_type(), args_type(), L, 1, fx);
|
||||
return stack::call_into_lua(return_type(), args_list(), L, 1, fx);
|
||||
}
|
||||
|
||||
template <typename R, typename V, V, typename T>
|
||||
|
@ -86,14 +86,14 @@ namespace function_detail {
|
|||
inline int call_wrapper_function(std::true_type, lua_State* L) {
|
||||
typedef meta::bind_traits<meta::unqualified_t<F>> traits_type;
|
||||
typedef typename traits_type::object_type T;
|
||||
typedef typename traits_type::args_type args_type;
|
||||
typedef typename traits_type::args_list args_list;
|
||||
typedef typename traits_type::return_type return_type;
|
||||
typedef meta::tuple_types<return_type> return_type_list;
|
||||
auto mfx = [&](auto&&... args) -> typename traits_type::return_type {
|
||||
auto& member = stack::get<T>(L, 1);
|
||||
return (member.*fx)(std::forward<decltype(args)>(args)...);
|
||||
};
|
||||
int n = stack::call_into_lua<1>(return_type_list(), args_type(), L, 2, mfx);
|
||||
int n = stack::call_into_lua<1>(return_type_list(), args_list(), L, 2, mfx);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ struct usertype_function_core : public base_function {
|
|||
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
||||
typedef functor<T, function_type> fx_t;
|
||||
typedef typename fx_t::traits_type traits_type;
|
||||
typedef typename fx_t::args_type args_type;
|
||||
typedef typename fx_t::args_list args_list;
|
||||
typedef typename fx_t::return_type return_type;
|
||||
|
||||
fx_t fx;
|
||||
|
@ -53,7 +53,7 @@ struct usertype_function : public usertype_function_core<Tp, Function> {
|
|||
typedef usertype_function_core<Tp, Function> base_t;
|
||||
typedef std::remove_pointer_t<Tp> T;
|
||||
typedef typename base_t::traits_type traits_type;
|
||||
typedef typename base_t::args_type args_type;
|
||||
typedef typename base_t::args_list args_list;
|
||||
typedef typename base_t::return_type return_type;
|
||||
|
||||
template<typename... Args>
|
||||
|
@ -66,7 +66,7 @@ struct usertype_function : public usertype_function_core<Tp, Function> {
|
|||
return luaL_error(L, "sol: received null for 'self' argument (use ':' for accessing member functions)");
|
||||
}
|
||||
#endif // Safety
|
||||
return static_cast<base_t&>(*this)(meta::tuple_types<return_type>(), args_type(), index_value<2>(), L);
|
||||
return static_cast<base_t&>(*this)(meta::tuple_types<return_type>(), args_list(), index_value<2>(), L);
|
||||
}
|
||||
|
||||
virtual int operator()(lua_State* L) override {
|
||||
|
@ -80,7 +80,7 @@ struct usertype_variable_function : public usertype_function_core<Tp, Function>
|
|||
typedef std::remove_pointer_t<Tp> T;
|
||||
typedef typename base_t::fx_t fx_t;
|
||||
typedef typename base_t::traits_type traits_type;
|
||||
typedef typename base_t::args_type args_type;
|
||||
typedef typename base_t::args_list args_list;
|
||||
typedef typename base_t::return_type return_type;
|
||||
typedef typename fx_t::can_read can_read;
|
||||
typedef typename fx_t::can_write can_write;
|
||||
|
@ -103,7 +103,7 @@ struct usertype_variable_function : public usertype_function_core<Tp, Function>
|
|||
}
|
||||
|
||||
int set_writable(std::true_type, lua_State* L) {
|
||||
return static_cast<base_t&>(*this)(meta::tuple_types<void>(), args_type(), index_value<3>(), L);
|
||||
return static_cast<base_t&>(*this)(meta::tuple_types<void>(), args_list(), index_value<3>(), L);
|
||||
}
|
||||
|
||||
int set_variable(std::false_type, lua_State* L) {
|
||||
|
|
|
@ -111,7 +111,7 @@ struct inheritance {
|
|||
return ti != typeid(Base) || type_check(types<Bases...>(), ti);
|
||||
}
|
||||
|
||||
static bool check(const std::type_info& ti) {
|
||||
static bool type_check(const std::type_info& ti) {
|
||||
return ti != typeid(T) || type_check(types<Bases...>(), ti);
|
||||
}
|
||||
|
||||
|
@ -125,14 +125,14 @@ struct inheritance {
|
|||
return ti != typeid(Base) ? type_cast(types<Bases...>(), data, ti) : static_cast<void*>(dynamic_cast<Base*>(static_cast<T*>(data)));
|
||||
}
|
||||
|
||||
static void* cast(void* voiddata, const std::type_info& ti) {
|
||||
static void* type_cast(void* voiddata, const std::type_info& ti) {
|
||||
T* data = static_cast<T*>(voiddata);
|
||||
return static_cast<void*>(ti != typeid(T) ? type_cast(types<Bases...>(), data, ti) : data);
|
||||
}
|
||||
};
|
||||
|
||||
using inheritance_check_function = decltype(&inheritance<void>::check);
|
||||
using inheritance_cast_function = decltype(&inheritance<void>::cast);
|
||||
using inheritance_check_function = decltype(&inheritance<void>::type_check);
|
||||
using inheritance_cast_function = decltype(&inheritance<void>::type_cast);
|
||||
#else
|
||||
template <typename T, typename... Bases>
|
||||
struct inheritance {
|
||||
|
@ -145,7 +145,7 @@ struct inheritance {
|
|||
return ti != id_for<Base>::value || type_check(types<Bases...>(), ti);
|
||||
}
|
||||
|
||||
static bool check(std::size_t ti) {
|
||||
static bool type_check(std::size_t ti) {
|
||||
return ti != id_for<T>::value || type_check(types<Bases...>(), ti);
|
||||
}
|
||||
|
||||
|
@ -159,14 +159,14 @@ struct inheritance {
|
|||
return ti != id_for<Base>::value ? type_cast(types<Bases...>(), data, ti) : static_cast<void*>(static_cast<Base*>(data));
|
||||
}
|
||||
|
||||
static void* cast(void* voiddata, std::size_t ti) {
|
||||
static void* type_cast(void* voiddata, std::size_t ti) {
|
||||
T* data = static_cast<T*>(voiddata);
|
||||
return static_cast<void*>(ti != id_for<T>::value ? type_cast(types<Bases...>(), data, ti) : data);
|
||||
}
|
||||
};
|
||||
|
||||
using inheritance_check_function = decltype(&inheritance<void>::check);
|
||||
using inheritance_cast_function = decltype(&inheritance<void>::cast);
|
||||
using inheritance_check_function = decltype(&inheritance<void>::type_check);
|
||||
using inheritance_cast_function = decltype(&inheritance<void>::type_cast);
|
||||
#endif // No Exceptions and/or No Runtime Type Information
|
||||
|
||||
} // detail
|
||||
|
|
85
sol/property.hpp
Normal file
85
sol/property.hpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
// 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_PROPERTY_HPP
|
||||
#define SOL_PROPERTY_HPP
|
||||
|
||||
namespace sol {
|
||||
|
||||
struct no_prop { };
|
||||
|
||||
template <typename R, typename W>
|
||||
struct property_wrapper {
|
||||
typedef std::integral_constant<bool, !std::is_void<R>::value> can_read;
|
||||
typedef std::integral_constant<bool, !std::is_void<W>::value> can_write;
|
||||
typedef std::conditional_t<can_read::value, R, no_prop> Read;
|
||||
typedef std::conditional_t<can_write::value, W, no_prop> Write;
|
||||
Read read;
|
||||
Write write;
|
||||
|
||||
template <typename Rx, typename Wx>
|
||||
property_wrapper(Rx&& r, Wx&& w) : read(std::forward<Rx>(r)), write(std::forward<Wx>(w)) {}
|
||||
};
|
||||
|
||||
namespace property_detail {
|
||||
template <typename R, typename W>
|
||||
inline decltype(auto) property(std::true_type, R&& read, W&& write) {
|
||||
return property_wrapper<std::decay_t<R>, std::decay_t<W>>(std::forward<R>(read), std::forward<W>(write));
|
||||
}
|
||||
template <typename W, typename R>
|
||||
inline decltype(auto) property(std::false_type, W&& write, R&& read) {
|
||||
return property_wrapper<std::decay_t<R>, std::decay_t<W>>(std::forward<R>(read), std::forward<W>(write));
|
||||
}
|
||||
template <typename R>
|
||||
inline decltype(auto) property(std::true_type, R&& read) {
|
||||
return property_wrapper<std::decay_t<R>, void>(std::forward<R>(read), no_prop());
|
||||
}
|
||||
template <typename W>
|
||||
inline decltype(auto) property(std::false_type, W&& write) {
|
||||
return property_wrapper<void, std::decay_t<W>>(no_prop(), std::forward<W>(write));
|
||||
}
|
||||
} // property_detail
|
||||
|
||||
template <typename F, typename G>
|
||||
inline decltype(auto) property(F&& f, G&& g) {
|
||||
using namespace sol;
|
||||
typedef lua_bind_traits<meta::unqualified_t<F>> left_traits;
|
||||
typedef lua_bind_traits<meta::unqualified_t<G>> right_traits;
|
||||
return property_detail::property(meta::boolean<(left_traits::arity < right_traits::arity)>(), std::forward<F>(f), std::forward<G>(g));
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline decltype(auto) property(F&& f) {
|
||||
using namespace sol;
|
||||
typedef lua_bind_traits<meta::unqualified_t<F>> left_traits;
|
||||
return property_detail::property(meta::boolean<(left_traits::arity == 0)>(), std::forward<F>(f));
|
||||
}
|
||||
|
||||
// Allow someone to make a member variable readonly (const)
|
||||
template <typename R, typename T>
|
||||
auto readonly(R T::* v) {
|
||||
typedef const R C;
|
||||
return static_cast<C T::*>(v);
|
||||
}
|
||||
|
||||
} // sol
|
||||
|
||||
#endif // SOL_PROPERTY_HPP
|
|
@ -26,6 +26,7 @@
|
|||
#include "stack.hpp"
|
||||
#include "protected_function_result.hpp"
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
|
||||
namespace sol {
|
||||
template <typename base_t>
|
||||
|
@ -86,7 +87,7 @@ private:
|
|||
|
||||
protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, handler& h) const {
|
||||
int stacksize = lua_gettop(base_t::lua_state());
|
||||
int firstreturn = std::max(1, stacksize - static_cast<int>(n) - 1);
|
||||
int firstreturn = (std::max)(1, stacksize - static_cast<int>(n) - 1);
|
||||
int returncount = 0;
|
||||
call_status code = call_status::ok;
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
|
|
|
@ -55,20 +55,20 @@ private:
|
|||
return stack::get<T>(L, index);
|
||||
}
|
||||
|
||||
sol::optional<sol::error> tagged_get( types<sol::optional<sol::error>> ) const {
|
||||
optional<error> tagged_get( types<optional<error>> ) const {
|
||||
if (valid()) {
|
||||
return nullopt;
|
||||
}
|
||||
return sol::error(detail::direct_error, stack::get<std::string>(L, index));
|
||||
return error(detail::direct_error, stack::get<std::string>(L, index));
|
||||
}
|
||||
|
||||
sol::error tagged_get( types<sol::error> ) const {
|
||||
error tagged_get( types<error> ) const {
|
||||
#ifdef SOL_CHECK_ARGUMENTS
|
||||
if (valid()) {
|
||||
type_panic(L, index, type_of(L, index), type::none);
|
||||
}
|
||||
#endif // Check Argument Safety
|
||||
return sol::error(detail::direct_error, stack::get<std::string>(L, index));
|
||||
return error(detail::direct_error, stack::get<std::string>(L, index));
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
|
@ -162,6 +162,14 @@ inline int call_into_lua(types<Ret0, Ret...>, types<Args...> ta, lua_State* L, i
|
|||
return push_reference(L, std::forward<decltype(r)>(r));
|
||||
}
|
||||
|
||||
template<int additionalpop = 0, bool check_args = stack_detail::default_check_arguments, typename Fx, typename... FxArgs>
|
||||
inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
|
||||
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits_type;
|
||||
typedef typename traits_type::args_list args_list;
|
||||
typedef typename traits_type::returns_list returns_list;
|
||||
return call_into_lua(returns_list(), args_list(), start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...)
|
||||
}
|
||||
|
||||
inline call_syntax get_call_syntax(lua_State* L, const std::string& key, int index = -2) {
|
||||
luaL_getmetatable(L, key.c_str());
|
||||
if (lua_compare(L, -1, index, LUA_OPEQ) == 1) {
|
||||
|
|
|
@ -164,6 +164,23 @@ struct checker<T, type::lightuserdata, C> {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename C>
|
||||
struct checker<userdata_value, type::userdata, C> {
|
||||
template <typename Handler>
|
||||
static bool check(lua_State* L, int index, Handler&& handler) {
|
||||
type t = type_of(L, index);
|
||||
bool success = t == type::userdata;
|
||||
if (!success) {
|
||||
// expected type, actual type
|
||||
handler(L, index, type::userdata, t);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename C>
|
||||
struct checker<user<T>, type::userdata, C> : checker<user<T>, type::lightuserdata, C> {};
|
||||
|
||||
template <typename T, typename C>
|
||||
struct checker<non_null<T>, type::userdata, C> : checker<T, lua_type_of<T>::value, C> {};
|
||||
|
||||
|
@ -235,77 +252,63 @@ struct checker<T*, type::userdata, C> {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename C>
|
||||
struct checker<userdata_value, type::userdata, C> {
|
||||
template <typename Handler>
|
||||
static bool check(lua_State* L, int index, Handler&& handler) {
|
||||
type t = type_of(L, index);
|
||||
bool success = t == type::userdata || t == type::lightuserdata;
|
||||
if (!success) {
|
||||
// expected type, actual type
|
||||
handler(L, index, type::lightuserdata, t);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename C>
|
||||
struct checker<T, type::userdata, C> {
|
||||
template <typename U, typename Handler>
|
||||
static bool check (types<U>, lua_State* L, type indextype, int index, Handler&& handler) {
|
||||
if (indextype != type::userdata) {
|
||||
handler(L, index, type::userdata, indextype);
|
||||
return false;
|
||||
}
|
||||
if (meta::any<std::is_same<T, light_userdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>::value)
|
||||
return true;
|
||||
if (lua_getmetatable(L, index) == 0) {
|
||||
return true;
|
||||
}
|
||||
if (stack_detail::check_metatable<U>(L))
|
||||
return true;
|
||||
if (stack_detail::check_metatable<U*>(L))
|
||||
return true;
|
||||
if (stack_detail::check_metatable<detail::unique_usertype<U>>(L))
|
||||
return true;
|
||||
template <typename U, typename Handler>
|
||||
static bool check(types<U>, lua_State* L, type indextype, int index, Handler&& handler) {
|
||||
if (indextype != type::userdata) {
|
||||
handler(L, index, type::userdata, indextype);
|
||||
return false;
|
||||
}
|
||||
if (meta::any<std::is_same<T, light_userdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>::value)
|
||||
return true;
|
||||
if (lua_getmetatable(L, index) == 0) {
|
||||
return true;
|
||||
}
|
||||
if (stack_detail::check_metatable<U>(L))
|
||||
return true;
|
||||
if (stack_detail::check_metatable<U*>(L))
|
||||
return true;
|
||||
if (stack_detail::check_metatable<detail::unique_usertype<U>>(L))
|
||||
return true;
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||
void* basecastdata = lua_touserdata(L, -1);
|
||||
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
|
||||
bool success = detail::catch_check<T>(basecast);
|
||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||
void* basecastdata = lua_touserdata(L, -1);
|
||||
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
|
||||
bool success = detail::catch_check<T>(basecast);
|
||||
#elif !defined(SOL_NO_RTTI)
|
||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||
if (stack::get<type>(L) == type::nil) {
|
||||
lua_pop(L, 2);
|
||||
return false;
|
||||
}
|
||||
void* basecastdata = lua_touserdata(L, -1);
|
||||
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
||||
bool success = ic(typeid(T));
|
||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||
if (stack::get<type>(L) == type::nil) {
|
||||
lua_pop(L, 2);
|
||||
return false;
|
||||
}
|
||||
void* basecastdata = lua_touserdata(L, -1);
|
||||
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
||||
bool success = ic(typeid(T));
|
||||
#else
|
||||
// Topkek
|
||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||
if (stack::get<type>(L) == type::nil) {
|
||||
lua_pop(L, 2);
|
||||
return false;
|
||||
}
|
||||
void* basecastdata = lua_touserdata(L, -1);
|
||||
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
||||
bool success = ic(detail::id_for<T>::value);
|
||||
// Topkek
|
||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||
if (stack::get<type>(L) == type::nil) {
|
||||
lua_pop(L, 2);
|
||||
return false;
|
||||
}
|
||||
void* basecastdata = lua_touserdata(L, -1);
|
||||
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
||||
bool success = ic(detail::id_for<T>::value);
|
||||
#endif // No Runtime Type Information || Exceptions
|
||||
lua_pop(L, 2);
|
||||
if (!success) {
|
||||
handler(L, index, type::userdata, indextype);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
lua_pop(L, 2);
|
||||
if (!success) {
|
||||
handler(L, index, type::userdata, indextype);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
static bool check (lua_State* L, int index, Handler&& handler) {
|
||||
const type indextype = type_of(L, index);
|
||||
return check(types<T>(), L, indextype, index, std::forward<Handler>(handler));
|
||||
}
|
||||
template <typename Handler>
|
||||
static bool check(lua_State* L, int index, Handler&& handler) {
|
||||
const type indextype = type_of(L, index);
|
||||
return check(types<T>(), L, indextype, index, std::forward<Handler>(handler));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -52,30 +52,44 @@ struct check_getter<optional<T>> {
|
|||
|
||||
template <typename T>
|
||||
struct check_getter<T, std::enable_if_t<std::is_integral<T>::value && lua_type_of<T>::value == type::number>> {
|
||||
template <typename Handler>
|
||||
static optional<T> get( lua_State* L, int index, Handler&& handler) {
|
||||
int isnum = 0;
|
||||
lua_Integer value = lua_tointegerx(L, index, &isnum);
|
||||
if (isnum == 0) {
|
||||
handler(L, index, type::number, type_of(L, index));
|
||||
return nullopt;
|
||||
}
|
||||
return static_cast<T>(value);
|
||||
}
|
||||
template <typename Handler>
|
||||
static optional<T> get(lua_State* L, int index, Handler&& handler) {
|
||||
int isnum = 0;
|
||||
lua_Integer value = lua_tointegerx(L, index, &isnum);
|
||||
if (isnum == 0) {
|
||||
handler(L, index, type::number, type_of(L, index));
|
||||
return nullopt;
|
||||
}
|
||||
return static_cast<T>(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct check_getter<T, std::enable_if_t<std::is_enum<T>::value>> {
|
||||
template <typename Handler>
|
||||
static optional<T> get(lua_State* L, int index, Handler&& handler) {
|
||||
int isnum = 0;
|
||||
lua_Integer value = lua_tointegerx(L, index, &isnum);
|
||||
if (isnum == 0) {
|
||||
handler(L, index, type::number, type_of(L, index));
|
||||
return nullopt;
|
||||
}
|
||||
return static_cast<T>(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct check_getter<T, std::enable_if_t<std::is_floating_point<T>::value>> {
|
||||
template <typename Handler>
|
||||
static optional<T> get( lua_State* L, int index, Handler&& handler) {
|
||||
int isnum = 0;
|
||||
lua_Number value = lua_tonumberx(L, index, &isnum);
|
||||
if (isnum == 0) {
|
||||
handler(L, index, type::number, type_of(L, index));
|
||||
return nullopt;
|
||||
}
|
||||
return static_cast<T>(value);
|
||||
}
|
||||
template <typename Handler>
|
||||
static optional<T> get(lua_State* L, int index, Handler&& handler) {
|
||||
int isnum = 0;
|
||||
lua_Number value = lua_tonumberx(L, index, &isnum);
|
||||
if (isnum == 0) {
|
||||
handler(L, index, type::number, type_of(L, index));
|
||||
return nullopt;
|
||||
}
|
||||
return static_cast<T>(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -202,6 +202,14 @@ inline decltype(auto) tagged_get(types<optional<T>>, lua_State* L, int index = -
|
|||
return stack_detail::unchecked_get<optional<T>>(L, index);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int alloc_destroy(lua_State* L) {
|
||||
void* rawdata = lua_touserdata(L, up_value_index(1));
|
||||
T* data = static_cast<T*>(rawdata);
|
||||
std::allocator<T> alloc;
|
||||
alloc.destroy(data);
|
||||
}
|
||||
|
||||
} // stack_detail
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -62,6 +62,13 @@ struct getter<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_unsigne
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct getter<T, std::enable_if_t<std::is_enum<T>::value>> {
|
||||
static T get(lua_State* L, int index = -1) {
|
||||
return static_cast<T>(lua_tointegerx(L, index, nullptr));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct getter<T, std::enable_if_t<std::is_base_of<reference, T>::value || std::is_base_of<stack_reference, T>::value>> {
|
||||
static T get(lua_State* L, int index = -1) {
|
||||
|
@ -83,6 +90,27 @@ struct getter<light_userdata_value> {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct getter<light<T>> {
|
||||
static light<T> get(lua_State* L, int index = -1) {
|
||||
return light<T>( static_cast<T*>(lua_touserdata(L, index)) );
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct getter<user<T>> {
|
||||
static T& get(lua_State* L, int index = -1) {
|
||||
return *static_cast<T*>(lua_touserdata(L, index));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct getter<user<T*>> {
|
||||
static T* get(lua_State* L, int index = -1) {
|
||||
return static_cast<T*>(lua_touserdata(L, index));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct getter<type> {
|
||||
static type get(lua_State *L, int index){
|
||||
|
@ -106,6 +134,15 @@ struct getter<std::string> {
|
|||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct getter<string_detail::string_shim> {
|
||||
string_detail::string_shim get(lua_State* L, int index) {
|
||||
size_t len;
|
||||
const char* p = lua_tolstring(L, index, &len);
|
||||
return string_detail::string_shim(p, len);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct getter<const char*> {
|
||||
static const char* get(lua_State* L, int index = -1) {
|
||||
|
@ -113,6 +150,17 @@ struct getter<const char*> {
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct getter<meta_function> {
|
||||
static meta_function get(lua_State *L, int index) {
|
||||
const char* name = getter<const char*>{}.get(L, index);
|
||||
for (std::size_t i = 0; i < meta_function_names.size(); ++i)
|
||||
if (meta_function_names[i] == name)
|
||||
return static_cast<meta_function>(i);
|
||||
return meta_function::construct;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct getter<char> {
|
||||
static char get(lua_State* L, int index = -1) {
|
||||
|
@ -208,9 +256,9 @@ struct getter<lua_CFunction> {
|
|||
|
||||
template<>
|
||||
struct getter<c_closure> {
|
||||
static c_closure get(lua_State* L, int index = -1) {
|
||||
return c_closure(lua_tocfunction(L, index), -1);
|
||||
}
|
||||
static c_closure get(lua_State* L, int index = -1) {
|
||||
return c_closure(lua_tocfunction(L, index), -1);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
|
|
|
@ -31,44 +31,54 @@ namespace sol {
|
|||
namespace stack {
|
||||
template<typename T, typename>
|
||||
struct pusher {
|
||||
template <typename... Args>
|
||||
static int push(lua_State* L, Args&&... args) {
|
||||
// Basically, we store all user-data like this:
|
||||
// If it's a movable/copyable value (no std::ref(x)), then we store the pointer to the new
|
||||
// data in the first sizeof(T*) bytes, and then however many bytes it takes to
|
||||
// do the actual object. Things that are std::ref or plain T* are stored as
|
||||
// just the sizeof(T*), and nothing else.
|
||||
T** pointerpointer = static_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||
T*& referencereference = *pointerpointer;
|
||||
T* allocationtarget = reinterpret_cast<T*>(pointerpointer + 1);
|
||||
referencereference = allocationtarget;
|
||||
std::allocator<T> alloc{};
|
||||
alloc.construct(allocationtarget, std::forward<Args>(args)...);
|
||||
luaL_newmetatable(L, &usertype_traits<T>::metatable[0]);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
template <typename K, typename... Args>
|
||||
static int push_keyed(lua_State* L, metatable_registry_key<K> k, Args&&... args) {
|
||||
// Basically, we store all user-data like this:
|
||||
// If it's a movable/copyable value (no std::ref(x)), then we store the pointer to the new
|
||||
// data in the first sizeof(T*) bytes, and then however many bytes it takes to
|
||||
// do the actual object. Things that are std::ref or plain T* are stored as
|
||||
// just the sizeof(T*), and nothing else.
|
||||
T** pointerpointer = static_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||
T*& referencereference = *pointerpointer;
|
||||
T* allocationtarget = reinterpret_cast<T*>(pointerpointer + 1);
|
||||
referencereference = allocationtarget;
|
||||
std::allocator<T> alloc{};
|
||||
alloc.construct(allocationtarget, std::forward<Args>(args)...);
|
||||
luaL_newmetatable(L, &k.key[0]);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <>
|
||||
struct pusher<detail::as_reference_tag> {
|
||||
template <typename T>
|
||||
static int push(lua_State* L, T&& obj) {
|
||||
return stack::push(L, detail::ptr(obj));
|
||||
}
|
||||
template <typename... Args>
|
||||
static int push(lua_State* L, Args&&... args) {
|
||||
return push_keyed(L, meta_registry_key(&usertype_traits<T*>::metatable[0]), std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pusher<T*> {
|
||||
static int push(lua_State* L, T* obj) {
|
||||
if (obj == nullptr)
|
||||
return stack::push(L, nil);
|
||||
T** pref = static_cast<T**>(lua_newuserdata(L, sizeof(T*)));
|
||||
*pref = obj;
|
||||
luaL_getmetatable(L, &usertype_traits<T*>::metatable[0]);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
template <typename K>
|
||||
static int push_keyed(lua_State* L, metatable_registry_key<K> k, T* obj) {
|
||||
if (obj == nullptr)
|
||||
return stack::push(L, nil);
|
||||
T** pref = static_cast<T**>(lua_newuserdata(L, sizeof(T*)));
|
||||
*pref = obj;
|
||||
luaL_getmetatable(L, &k.key[0]);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int push(lua_State* L, T* obj) {
|
||||
return push_keyed(L, meta_registry_key(&usertype_traits<T*>::metatable[0]), obj);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct pusher<detail::as_reference_tag> {
|
||||
template <typename T>
|
||||
static int push(lua_State* L, T&& obj) {
|
||||
return stack::push(L, detail::ptr(obj));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
@ -127,6 +137,16 @@ struct pusher<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_signed<
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pusher<T, std::enable_if_t<std::is_enum<T>::value>> {
|
||||
static int push(lua_State* L, const T& value) {
|
||||
if (std::is_same<char, T>::value) {
|
||||
return stack::push(L, static_cast<int>(value));
|
||||
}
|
||||
return stack::push(L, static_cast<std::underlying_type_t<T>>(value));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pusher<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_unsigned<T>>::value>> {
|
||||
static int push(lua_State* L, const T& value) {
|
||||
|
@ -136,7 +156,7 @@ struct pusher<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_unsigne
|
|||
};
|
||||
|
||||
template<typename T>
|
||||
struct pusher<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::neg<meta::has_key_value_pair<T>>, meta::neg<std::is_base_of<reference, T>>>::value>> {
|
||||
struct pusher<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::neg<meta::has_key_value_pair<T>>, meta::neg<meta::any<std::is_base_of<reference, T>, std::is_base_of<stack_reference, T>>>>::value>> {
|
||||
static int push(lua_State* L, const T& cont) {
|
||||
lua_createtable(L, static_cast<int>(cont.size()), 0);
|
||||
int tableindex = lua_gettop(L);
|
||||
|
@ -149,7 +169,7 @@ struct pusher<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::neg<me
|
|||
};
|
||||
|
||||
template<typename T>
|
||||
struct pusher<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::has_key_value_pair<T>, meta::neg<std::is_base_of<reference, T>>>::value>> {
|
||||
struct pusher<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::has_key_value_pair<T>, meta::neg<meta::any<std::is_base_of<reference, T>, std::is_base_of<stack_reference, T>>>>::value>> {
|
||||
static int push(lua_State* L, const T& cont) {
|
||||
lua_createtable(L, static_cast<int>(cont.size()), 0);
|
||||
int tableindex = lua_gettop(L);
|
||||
|
@ -213,12 +233,26 @@ struct pusher<lua_CFunction> {
|
|||
|
||||
template<>
|
||||
struct pusher<c_closure> {
|
||||
static int push(lua_State* L, c_closure closure) {
|
||||
lua_pushcclosure(L, closure.c_function, closure.upvalues);
|
||||
static int push(lua_State* L, c_closure cc) {
|
||||
lua_pushcclosure(L, cc.c_function, cc.upvalues);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Arg, typename... Args>
|
||||
struct pusher<closure<Arg, Args...>> {
|
||||
template <std::size_t... I, typename T>
|
||||
static int push(std::index_sequence<I...>, lua_State* L, T&& c) {
|
||||
int pushcount = multi_push(L, detail::forward_get<I>(c.upvalues)...);
|
||||
return stack::push(L, c_closure(c.c_function, pushcount));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static int push(lua_State* L, T&& c) {
|
||||
return push(std::make_index_sequence<1 + sizeof...(Args)>(), L, std::forward<T>(c));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct pusher<void*> {
|
||||
static int push(lua_State* L, void* userdata) {
|
||||
|
@ -235,6 +269,31 @@ struct pusher<light_userdata_value> {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pusher<light<T>> {
|
||||
static int push(lua_State* L, light<T> l) {
|
||||
lua_pushlightuserdata(L, static_cast<void*>(l.value));
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pusher<user<T>> {
|
||||
template <typename... Args>
|
||||
static int push(lua_State* L, Args&&... args ) {
|
||||
// A dumb pusher
|
||||
void* rawdata = lua_newuserdata(L, sizeof(T));
|
||||
std::allocator<T> alloc;
|
||||
alloc.construct(static_cast<T*>(rawdata), std::forward<Args>(args)...);
|
||||
lua_CFunction cdel = stack_detail::alloc_destroy<T>;
|
||||
// Make sure we have a plain GC set for this data
|
||||
lua_pushlightuserdata(L, rawdata);
|
||||
lua_pushcclosure(L, cdel, 1);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct pusher<userdata_value> {
|
||||
static int push(lua_State* L, userdata_value data) {
|
||||
|
@ -276,6 +335,15 @@ struct pusher<std::string> {
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct pusher<meta_function> {
|
||||
static int push(lua_State* L, meta_function m) {
|
||||
const std::string& str = name_of(m);
|
||||
lua_pushlstring(L, str.c_str(), str.size());
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
|
|
48
sol/string_shim.hpp
Normal file
48
sol/string_shim.hpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
namespace sol {
|
||||
namespace string_detail {
|
||||
struct string_shim {
|
||||
std::size_t s;
|
||||
const char* p;
|
||||
|
||||
string_shim(std::string& r) : string_shim(r.data(), r.size()) {}
|
||||
string_shim(const char* p) : string_shim(p, std::char_traits<char>::length(p)) {}
|
||||
string_shim(const char* p, std::size_t s) : s(s), p(p) {}
|
||||
|
||||
static int compare(const char* lhs_p, std::size_t lhs_sz, const char* rhs_p, std::size_t rhs_sz) {
|
||||
int result = std::char_traits<char>::compare(lhs_p, rhs_p, lhs_sz < rhs_sz ? lhs_sz : rhs_sz);
|
||||
if (result != 0)
|
||||
return result;
|
||||
if (lhs_sz < rhs_sz)
|
||||
return -1;
|
||||
if (lhs_sz > rhs_sz)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* data() const {
|
||||
return p;
|
||||
}
|
||||
|
||||
std::size_t size() const {
|
||||
return s;
|
||||
}
|
||||
|
||||
bool operator==(const string_shim& r) const {
|
||||
return compare(p, s, r.data(), r.size()) == 0;
|
||||
}
|
||||
|
||||
bool operator==(const char* r) const {
|
||||
return compare(r, std::char_traits<char>::length(r), p, s) == 0;
|
||||
}
|
||||
|
||||
bool operator==(const std::string& r) const {
|
||||
return compare(r.data(), r.size(), p, s) == 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
159
sol/traits.hpp
159
sol/traits.hpp
|
@ -23,6 +23,7 @@
|
|||
#define SOL_TRAITS_HPP
|
||||
|
||||
#include "tuple.hpp"
|
||||
#include "bind_traits.hpp"
|
||||
#include <type_traits>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
@ -54,6 +55,9 @@ struct unwrapped<std::reference_wrapper<T>> {
|
|||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using unwrapped_t = typename unwrapped<T>::type;
|
||||
|
||||
template<typename T>
|
||||
struct remove_member_pointer;
|
||||
|
||||
|
@ -117,21 +121,6 @@ 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 T>
|
||||
using unqualified = std::remove_cv<std::remove_reference_t<T>>;
|
||||
|
||||
template<typename T>
|
||||
using unqualified_t = typename unqualified<T>::type;
|
||||
|
||||
template<typename T>
|
||||
using unwrapped_t = typename unwrapped<T>::type;
|
||||
|
||||
template <std::size_t N, typename Tuple>
|
||||
using tuple_element = std::tuple_element<N, unqualified_t<Tuple>>;
|
||||
|
||||
template <std::size_t N, typename Tuple>
|
||||
using tuple_element_t = std::tuple_element_t<N, unqualified_t<Tuple>>;
|
||||
|
||||
template<typename V, typename... Vs>
|
||||
struct find_in_pack_v : boolean<false> { };
|
||||
|
||||
|
@ -252,151 +241,11 @@ struct is_callable<T, true> {
|
|||
static const bool value = sizeof(test<Derived>(0)) == sizeof(yes);
|
||||
};
|
||||
|
||||
template<class F>
|
||||
struct check_deducible_signature {
|
||||
struct nat {};
|
||||
template<class G>
|
||||
static auto test(int) -> decltype(&G::operator(), void());
|
||||
template<class>
|
||||
static auto test(...) -> nat;
|
||||
|
||||
using type = std::is_void<decltype(test<F>(0))>;
|
||||
};
|
||||
} // meta_detail
|
||||
|
||||
template<class F>
|
||||
struct has_deducible_signature : meta_detail::check_deducible_signature<F>::type { };
|
||||
|
||||
template<typename T>
|
||||
struct is_callable : boolean<meta_detail::is_callable<T>::value> {};
|
||||
|
||||
namespace meta_detail {
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
struct void_tuple_element : meta::tuple_element<I, T> {};
|
||||
|
||||
template <std::size_t I>
|
||||
struct void_tuple_element<I, std::tuple<>> { typedef void type; };
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
using void_tuple_element_t = typename void_tuple_element<I, T>::type;
|
||||
|
||||
template<typename Signature, bool b = has_deducible_signature<Signature>::value>
|
||||
struct fx_traits {
|
||||
static const bool is_member_function = false;
|
||||
static const std::size_t arity = 0;
|
||||
typedef types<> args_type;
|
||||
typedef std::tuple<> args_tuple_type;
|
||||
typedef void object_type;
|
||||
typedef void function_pointer_type;
|
||||
typedef void function_type;
|
||||
typedef void free_function_pointer_type;
|
||||
typedef void signature_type;
|
||||
typedef void return_type;
|
||||
template<std::size_t i>
|
||||
using arg_at = void_tuple_element_t<i, args_tuple_type>;
|
||||
};
|
||||
|
||||
template<typename Signature>
|
||||
struct fx_traits<Signature, true> : fx_traits<decltype(&Signature::operator()), false> {};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...), false> {
|
||||
static const std::size_t arity = sizeof...(Args);
|
||||
static const bool is_member_function = true;
|
||||
typedef T object_type;
|
||||
typedef std::tuple<Args...> args_tuple_type;
|
||||
typedef types<Args...> args_type;
|
||||
typedef R(T::* function_pointer_type)(Args...);
|
||||
typedef std::remove_pointer_t<function_pointer_type> function_type;
|
||||
typedef R(*free_function_pointer_type)(Args...);
|
||||
typedef R return_type;
|
||||
typedef std::remove_pointer_t<free_function_pointer_type> signature_type;
|
||||
template<std::size_t i>
|
||||
using arg_at = void_tuple_element_t<i, args_tuple_type>;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const, false> {
|
||||
static const std::size_t arity = sizeof...(Args);
|
||||
static const bool is_member_function = true;
|
||||
typedef T object_type;
|
||||
typedef std::tuple<Args...> args_tuple_type;
|
||||
typedef types<Args...> args_type;
|
||||
typedef R(T::* function_pointer_type)(Args...);
|
||||
typedef std::remove_pointer_t<function_pointer_type> function_type;
|
||||
typedef R(*free_function_pointer_type)(Args...);
|
||||
typedef R return_type;
|
||||
typedef std::remove_pointer_t<free_function_pointer_type> signature_type;
|
||||
template<std::size_t i>
|
||||
using arg_at = void_tuple_element_t<i, args_tuple_type>;
|
||||
};
|
||||
|
||||
template<typename R, typename... Args>
|
||||
struct fx_traits<R(Args...), false> {
|
||||
static const std::size_t arity = sizeof...(Args);
|
||||
static const bool is_member_function = false;
|
||||
typedef std::tuple<Args...> args_tuple_type;
|
||||
typedef types<Args...> args_type;
|
||||
typedef R(function_type)(Args...);
|
||||
typedef R(*function_pointer_type)(Args...);
|
||||
typedef R(*free_function_pointer_type)(Args...);
|
||||
typedef R return_type;
|
||||
typedef std::remove_pointer_t<free_function_pointer_type> signature_type;
|
||||
template<std::size_t i>
|
||||
using arg_at = void_tuple_element_t<i, args_tuple_type>;
|
||||
};
|
||||
|
||||
template<typename R, typename... Args>
|
||||
struct fx_traits<R(*)(Args...), false> {
|
||||
static const std::size_t arity = sizeof...(Args);
|
||||
static const bool is_member_function = false;
|
||||
typedef std::tuple<Args...> args_tuple_type;
|
||||
typedef types<Args...> args_type;
|
||||
typedef R(function_type)(Args...);
|
||||
typedef R(*function_pointer_type)(Args...);
|
||||
typedef R(*free_function_pointer_type)(Args...);
|
||||
typedef R return_type;
|
||||
typedef std::remove_pointer_t<free_function_pointer_type> signature_type;
|
||||
template<std::size_t i>
|
||||
using arg_at = void_tuple_element_t<i, args_tuple_type>;
|
||||
};
|
||||
|
||||
template<typename Signature, bool b = std::is_member_object_pointer<Signature>::value>
|
||||
struct callable_traits : fx_traits<std::decay_t<Signature>> {
|
||||
|
||||
};
|
||||
|
||||
template<typename R, typename T>
|
||||
struct callable_traits<R(T::*), true> {
|
||||
typedef R Arg;
|
||||
typedef T object_type;
|
||||
using signature_type = R(T::*);
|
||||
static const bool is_member_function = false;
|
||||
static const std::size_t arity = 1;
|
||||
typedef std::tuple<Arg> args_tuple_type;
|
||||
typedef types<Arg> args_type;
|
||||
typedef R return_type;
|
||||
typedef R(function_type)(Arg);
|
||||
typedef R(*function_pointer_type)(Arg);
|
||||
typedef R(*free_function_pointer_type)(Arg);
|
||||
template<std::size_t i>
|
||||
using arg_at = void_tuple_element_t<i, args_tuple_type>;
|
||||
};
|
||||
} // meta_detail
|
||||
|
||||
template<typename Signature>
|
||||
struct bind_traits : meta_detail::callable_traits<std::remove_volatile_t<Signature>> {};
|
||||
|
||||
template<typename Signature>
|
||||
using function_args_t = typename bind_traits<Signature>::args_type;
|
||||
|
||||
template<typename Signature>
|
||||
using function_signature_t = typename bind_traits<Signature>::signature_type;
|
||||
|
||||
template<typename Signature>
|
||||
using function_return_t = typename bind_traits<Signature>::return_type;
|
||||
|
||||
struct has_begin_end_impl {
|
||||
template<typename T, typename U = unqualified_t<T>,
|
||||
typename B = decltype(std::declval<U&>().begin()),
|
||||
|
|
|
@ -41,6 +41,12 @@ template<typename... Args>
|
|||
struct tuple_types_<std::tuple<Args...>> { typedef types<Args...> type; };
|
||||
} // detail
|
||||
|
||||
template<typename T>
|
||||
using unqualified = std::remove_cv<std::remove_reference_t<T>>;
|
||||
|
||||
template<typename T>
|
||||
using unqualified_t = typename unqualified<T>::type;
|
||||
|
||||
template<typename... Args>
|
||||
using tuple_types = typename detail::tuple_types_<Args...>::type;
|
||||
|
||||
|
@ -50,8 +56,18 @@ struct pop_front_type;
|
|||
template<typename Arg>
|
||||
using pop_front_type_t = typename pop_front_type<Arg>::type;
|
||||
|
||||
template<typename... Args>
|
||||
struct pop_front_type<types<Args...>> { typedef void front_type; typedef types<Args...> type; };
|
||||
|
||||
template<typename Arg, typename... Args>
|
||||
struct pop_front_type<types<Arg, Args...>> { typedef types<Args...> type; };
|
||||
struct pop_front_type<types<Arg, Args...>> { typedef Arg front_type; typedef types<Args...> type; };
|
||||
|
||||
template <std::size_t N, typename Tuple>
|
||||
using tuple_element = std::tuple_element<N, unqualified_t<Tuple>>;
|
||||
|
||||
template <std::size_t N, typename Tuple>
|
||||
using tuple_element_t = std::tuple_element_t<N, unqualified_t<Tuple>>;
|
||||
|
||||
} // meta
|
||||
} // sol
|
||||
|
||||
|
|
101
sol/types.hpp
101
sol/types.hpp
|
@ -22,9 +22,10 @@
|
|||
#ifndef SOL_TYPES_HPP
|
||||
#define SOL_TYPES_HPP
|
||||
|
||||
#include "optional.hpp"
|
||||
#include "compatibility.hpp"
|
||||
#include "traits.hpp"
|
||||
#include "optional.hpp"
|
||||
#include "string_shim.hpp"
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
|
@ -83,8 +84,6 @@ inline int c_trampoline(lua_State* L, lua_CFunction f) {
|
|||
return trampoline(L, f);
|
||||
}
|
||||
#endif // Exceptions vs. No Exceptions
|
||||
struct empty { void operator()() {} };
|
||||
|
||||
template <typename T>
|
||||
struct unique_usertype {};
|
||||
} // detail
|
||||
|
@ -174,12 +173,72 @@ struct userdata_value {
|
|||
operator void*() const { return value; }
|
||||
};
|
||||
|
||||
struct c_closure {
|
||||
lua_CFunction c_function;
|
||||
int upvalues;
|
||||
c_closure(lua_CFunction f, int upvalues = 0) : c_function(f), upvalues(upvalues) {}
|
||||
template <typename L>
|
||||
struct light {
|
||||
L* value;
|
||||
|
||||
light(L& x) : value(std::addressof(x)) {}
|
||||
light(L* x) : value(x) {}
|
||||
light(void* x) : value(static_cast<L*>(x)) {}
|
||||
operator L* () const { return value; }
|
||||
operator L& () const { return *value; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
auto make_light(T& l) {
|
||||
typedef meta::unwrapped_t<std::remove_pointer_t<std::remove_pointer_t<T>>> L;
|
||||
return light<L>(l);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
struct user {
|
||||
U value;
|
||||
|
||||
user(U x) : value(std::forward<U>(x)) {}
|
||||
operator U* () const { return std::addressof(value); }
|
||||
operator U& () const { return value; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
auto make_user(T&& u) {
|
||||
typedef meta::unwrapped_t<meta::unqualified_t<T>> U;
|
||||
return user<U>(std::forward<T>(u));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct metatable_registry_key {
|
||||
T key;
|
||||
|
||||
metatable_registry_key(T key) : key(std::forward<T>(key)) {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
auto meta_registry_key(T&& key) {
|
||||
typedef meta::unqualified_t<T> K;
|
||||
return metatable_registry_key<K>(std::forward<T>(key));
|
||||
}
|
||||
|
||||
template <typename... Upvalues>
|
||||
struct closure {
|
||||
lua_CFunction c_function;
|
||||
std::tuple<Upvalues...> upvalues;
|
||||
closure(lua_CFunction f, Upvalues... upvalues) : c_function(f), upvalues(std::forward<Upvalues>(upvalues)...) {}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct closure<> {
|
||||
lua_CFunction c_function;
|
||||
int upvalues;
|
||||
closure(lua_CFunction f, int upvalues = 0) : c_function(f), upvalues(upvalues) {}
|
||||
};
|
||||
|
||||
typedef closure<> c_closure;
|
||||
|
||||
template <typename... Args>
|
||||
closure<Args...> make_closure(lua_CFunction f, Args&&... args) {
|
||||
return closure<Args...>(f, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
struct this_state {
|
||||
lua_State* L;
|
||||
operator lua_State* () const {
|
||||
|
@ -262,6 +321,8 @@ enum class meta_function {
|
|||
call_function = call,
|
||||
};
|
||||
|
||||
typedef meta_function meta_method;
|
||||
|
||||
const std::array<std::string, 2> meta_variable_names = { {
|
||||
"__index",
|
||||
"__newindex",
|
||||
|
@ -320,7 +381,7 @@ inline void type_error(lua_State* L, type expected, type actual) {
|
|||
|
||||
inline void type_assert(lua_State* L, int index, type expected, type actual) {
|
||||
if (expected != type::poly && expected != actual) {
|
||||
type_panic(L, index, expected, actual);
|
||||
type_panic(L, index, expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -373,6 +434,7 @@ class thread;
|
|||
struct variadic_args;
|
||||
struct this_state;
|
||||
|
||||
namespace detail {
|
||||
template <typename T, typename = void>
|
||||
struct lua_type_of : std::integral_constant<type, type::userdata> {};
|
||||
|
||||
|
@ -421,6 +483,9 @@ struct lua_type_of<const char16_t*> : std::integral_constant<type, type::string>
|
|||
template <>
|
||||
struct lua_type_of<const char32_t*> : std::integral_constant<type, type::string> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<string_detail::string_shim> : std::integral_constant<type, type::string> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<bool> : std::integral_constant<type, type::boolean> {};
|
||||
|
||||
|
@ -457,6 +522,12 @@ struct lua_type_of<light_userdata_value> : std::integral_constant<type, type::li
|
|||
template <>
|
||||
struct lua_type_of<userdata_value> : std::integral_constant<type, type::userdata> {};
|
||||
|
||||
template <typename T>
|
||||
struct lua_type_of<light<T>> : std::integral_constant<type, type::lightuserdata> {};
|
||||
|
||||
template <typename T>
|
||||
struct lua_type_of<user<T>> : std::integral_constant<type, type::userdata> {};
|
||||
|
||||
template <typename Base>
|
||||
struct lua_type_of<basic_lightuserdata<Base>> : std::integral_constant<type, type::lightuserdata> {};
|
||||
|
||||
|
@ -499,8 +570,15 @@ struct lua_type_of<T, std::enable_if_t<std::is_arithmetic<T>::value>> : std::int
|
|||
template <typename T>
|
||||
struct lua_type_of<T, std::enable_if_t<std::is_enum<T>::value>> : std::integral_constant<type, type::number> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<sol::meta_function> : std::integral_constant<type, type::string> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<this_state> : std::integral_constant<type, type::none> {};
|
||||
} // detail
|
||||
|
||||
template <typename T>
|
||||
struct lua_type_of : detail::lua_type_of<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct is_lua_primitive : std::integral_constant<bool,
|
||||
|
@ -544,7 +622,10 @@ struct lua_bind_traits : meta::bind_traits<Signature> {
|
|||
private:
|
||||
typedef meta::bind_traits<Signature> base_t;
|
||||
public:
|
||||
static const std::size_t arity = base_t::arity - meta::count_for<is_transparent_argument, typename base_t::args_type>::value;
|
||||
static const std::size_t true_arity = base_t::arity;
|
||||
static const std::size_t arity = base_t::arity - meta::count_for<is_transparent_argument, typename base_t::args_list>::value;
|
||||
static const std::size_t true_free_arity = base_t::free_arity;
|
||||
static const std::size_t free_arity = base_t::free_arity - meta::count_for<is_transparent_argument, typename base_t::args_list>::value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
@ -555,7 +636,7 @@ struct is_table<basic_table_core<x, T>> : std::true_type {};
|
|||
|
||||
template<typename T>
|
||||
inline type type_of() {
|
||||
return lua_type_of<meta::unqualified_t<T>>::value;
|
||||
return lua_type_of<meta::unqualified_t<T>>::value;
|
||||
}
|
||||
} // sol
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include "inheritance.hpp"
|
||||
#include "raii.hpp"
|
||||
#include "deprecate.hpp"
|
||||
#include "usertype_metatable.hpp"
|
||||
#include "stack.hpp"
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
|
@ -422,13 +424,13 @@ private:
|
|||
#elif !defined(SOL_NO_RTTI)
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
baseclasscheck = (void*)&detail::inheritance<T, Bases...>::check;
|
||||
baseclasscast = (void*)&detail::inheritance<T, Bases...>::cast;
|
||||
baseclasscheck = (void*)&detail::inheritance<T, Bases...>::type_check;
|
||||
baseclasscast = (void*)&detail::inheritance<T, Bases...>::type_cast;
|
||||
#else
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
baseclasscheck = (void*)&detail::inheritance<T, Bases...>::check;
|
||||
baseclasscast = (void*)&detail::inheritance<T, Bases...>::cast;
|
||||
baseclasscheck = (void*)&detail::inheritance<T, Bases...>::type_check;
|
||||
baseclasscast = (void*)&detail::inheritance<T, Bases...>::type_cast;
|
||||
#endif // No Runtime Type Information vs. Throw-Style Inheritance
|
||||
}
|
||||
|
||||
|
|
187
sol/usertype_metatable.hpp
Normal file
187
sol/usertype_metatable.hpp
Normal file
|
@ -0,0 +1,187 @@
|
|||
// 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_USERTYPE_METATABLE_HPP
|
||||
#define SOL_USERTYPE_METATABLE_HPP
|
||||
|
||||
#include "wrapper.hpp"
|
||||
#include "call.hpp"
|
||||
#include "stack.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
namespace sol {
|
||||
|
||||
namespace usertype_detail {
|
||||
inline bool is_index(string_detail::string_shim s) {
|
||||
return s == name_of(meta_function::index) || s == name_of(meta_function::new_index);
|
||||
}
|
||||
|
||||
inline bool is_index(meta_function mf) {
|
||||
return mf == meta_function::index || mf == meta_function::new_index;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename Tuple>
|
||||
struct usertype_metatable {
|
||||
typedef std::make_index_sequence<std::tuple_size<Tuple>::value> indices;
|
||||
typedef std::make_index_sequence<std::tuple_size<Tuple>::value / 2> half_indices;
|
||||
template <std::size_t I>
|
||||
struct check_binding : is_variable_binding<std::tuple_element_t<I, Tuple>> {};
|
||||
Tuple functions;
|
||||
bool must_index;
|
||||
|
||||
template <std::size_t... I>
|
||||
static bool contains_variable(std::index_sequence<I...>) {
|
||||
typedef meta::any<check_binding<(I * 2 + 1)>...> has_variables;
|
||||
return has_variables::value;
|
||||
}
|
||||
|
||||
template <std::size_t... I>
|
||||
bool contains_index(std::index_sequence<I...>) const {
|
||||
bool idx = false;
|
||||
detail::swallow{ 0, ((idx &= usertype_detail::is_index(std::get<I * 2>(functions))), 0) ... };
|
||||
return idx;
|
||||
}
|
||||
|
||||
usertype_metatable(Tuple t) : functions(std::move(t)), must_index(contains_variable(half_indices()) || contains_index(half_indices())) {}
|
||||
|
||||
template <bool is_index>
|
||||
int find_call(std::integral_constant<bool, is_index>, std::index_sequence<>, lua_State* L, const sol::string_detail::string_shim& accessor) {
|
||||
return luaL_error(L, "sol: attempt to index nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.data());
|
||||
}
|
||||
|
||||
template <bool is_index, std::size_t I0, std::size_t I1, std::size_t... In>
|
||||
int find_call(std::integral_constant<bool, is_index> idx, std::index_sequence<I0, I1, In...>, lua_State* L, const sol::string_detail::string_shim& accessor) {
|
||||
string_detail::string_shim name(std::get<I0>(functions));
|
||||
if (accessor == name) {
|
||||
if (is_variable_binding<decltype(std::get<I1>(functions))>::value) {
|
||||
return call_with<I1, is_index, true>(L, *this);
|
||||
}
|
||||
return stack::push(L, c_closure(call<I1, is_index>, stack::push(L, light<usertype_metatable>(*this))));
|
||||
}
|
||||
return find_call(idx, std::index_sequence<In...>(), L, accessor);
|
||||
}
|
||||
|
||||
template <std::size_t I, bool is_index = true, bool is_variable = false>
|
||||
static int call(lua_State* L) {
|
||||
usertype_metatable& f = stack::get<light<usertype_metatable>>(L, up_value_index(1));
|
||||
return call_with<I, is_index, is_variable>(L, f);
|
||||
}
|
||||
|
||||
template <std::size_t I, bool is_index = true, bool is_variable = false>
|
||||
static int call_with(lua_State* L, usertype_metatable& um) {
|
||||
auto& f = call_detail::pick(std::integral_constant<bool, is_index>(), std::get<I>(um.functions));
|
||||
return call_detail::call_wrapped<T, is_index, is_variable>(L, f);
|
||||
}
|
||||
|
||||
static int index_call(lua_State* L) {
|
||||
usertype_metatable& f = stack::get<light<usertype_metatable>>(L, up_value_index(1));
|
||||
string_detail::string_shim accessor = stack::get<string_detail::string_shim>(L, -1);
|
||||
return f.find_call(std::true_type(), std::make_index_sequence<std::tuple_size<Tuple>::value>(), L, accessor);
|
||||
}
|
||||
|
||||
static int new_index_call(lua_State* L) {
|
||||
usertype_metatable& f = stack::get<light<usertype_metatable>>(L, up_value_index(1));
|
||||
string_detail::string_shim accessor = stack::get<string_detail::string_shim>(L, -2);
|
||||
return f.find_call(std::false_type(), std::make_index_sequence<std::tuple_size<Tuple>::value>(), L, accessor);
|
||||
}
|
||||
|
||||
static int gc_call(lua_State* L) {
|
||||
stack_object o(L, 1);
|
||||
type x = o.get_type();
|
||||
usertype_metatable& f = stack::get<light<usertype_metatable>>(L, up_value_index(1));
|
||||
f.~usertype_metatable();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
namespace stack {
|
||||
|
||||
template <typename T, typename Tuple>
|
||||
struct pusher<usertype_metatable<T, Tuple>> {
|
||||
typedef usertype_metatable<T, Tuple> umt_t;
|
||||
|
||||
static void cleanup(lua_State* L, int metaidx, usertype_metatable<T, Tuple>&& um) {
|
||||
const char* metakey = &usertype_traits<T>::gc_table[0];
|
||||
lua_createtable(L, 1, 0);
|
||||
stack_table t(L, -1);
|
||||
t[meta_function::garbage_collect] = umt_t::gc_call;
|
||||
stack::set_field(L, metakey, t, metaidx);
|
||||
}
|
||||
|
||||
template <std::size_t... I>
|
||||
static int push(std::index_sequence<I...>, lua_State* L, usertype_metatable<T, Tuple>&& um) {
|
||||
// Basic index pushing: specialize
|
||||
// index and newindex to give variables and stuff
|
||||
// make sure to return final T metatable table
|
||||
const bool mustindex = um.must_index;
|
||||
for (std::size_t i = 0; i < 3; ++i) {
|
||||
// Pointer types, AKA "references" from C++
|
||||
const char* metakey = nullptr;
|
||||
switch (i) {
|
||||
case 0:
|
||||
metakey = &usertype_traits<T*>::metatable[0];
|
||||
break;
|
||||
case 1:
|
||||
metakey = &usertype_traits<detail::unique_usertype<T>>::metatable[0];
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
metakey = &usertype_traits<T>::metatable[0];
|
||||
break;
|
||||
}
|
||||
luaL_newmetatable(L, metakey);
|
||||
stack_table t(L, -1);
|
||||
stack::push(L, make_light(um));
|
||||
luaL_Reg l[] = {
|
||||
{ &std::get<I * 2>(um.functions)[0], umt_t::call<(I * 2) + 1> }...,
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
luaL_setfuncs(L, l, 1);
|
||||
|
||||
if (mustindex) {
|
||||
t[meta_function::index] = make_closure(umt_t::index_call, make_light(um));
|
||||
t[meta_function::new_index] = make_closure(umt_t::new_index_call, make_light(um));
|
||||
}
|
||||
else {
|
||||
t[meta_function::index] = t;
|
||||
}
|
||||
if (i < 2) {
|
||||
// We want to just leave the table
|
||||
// in the registry only, otherwise we return it
|
||||
t.pop();
|
||||
}
|
||||
}
|
||||
int metaidx = lua_gettop(L);
|
||||
cleanup(L, metaidx, std::move(um));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int push(lua_State* L, usertype_metatable<T, Tuple>&& um) {
|
||||
return push(std::make_index_sequence<std::tuple_size<Tuple>::value / 2>(), L, std::move(um));
|
||||
}
|
||||
};
|
||||
|
||||
} // stack
|
||||
|
||||
} // sol
|
||||
|
||||
#endif // SOL_USERTYPE_METATABLE_HPP
|
|
@ -41,7 +41,7 @@ namespace sol {
|
|||
int stacktop;
|
||||
stack_proxy sp;
|
||||
|
||||
va_iterator() : L(nullptr), index(std::numeric_limits<int>::max()), stacktop(std::numeric_limits<int>::max()) {}
|
||||
va_iterator() : L(nullptr), index((std::numeric_limits<int>::max)()), stacktop((std::numeric_limits<int>::max)()) {}
|
||||
va_iterator(lua_State* L, int index, int stacktop) : L(L), index(index), stacktop(stacktop), sp(L, index) {}
|
||||
|
||||
reference operator*() {
|
||||
|
@ -100,10 +100,10 @@ namespace sol {
|
|||
}
|
||||
|
||||
bool operator==(const va_iterator& r) const {
|
||||
if (stacktop == std::numeric_limits<int>::max()) {
|
||||
if (stacktop == (std::numeric_limits<int>::max)()) {
|
||||
return r.index == r.stacktop;
|
||||
}
|
||||
else if (r.stacktop == std::numeric_limits<int>::max()) {
|
||||
else if (r.stacktop == (std::numeric_limits<int>::max)()) {
|
||||
return index == stacktop;
|
||||
}
|
||||
return index == r.index;
|
||||
|
|
209
sol/wrapper.hpp
Normal file
209
sol/wrapper.hpp
Normal file
|
@ -0,0 +1,209 @@
|
|||
// 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_WRAPPER_HPP
|
||||
#define SOL_WRAPPER_HPP
|
||||
|
||||
#include "types.hpp"
|
||||
|
||||
namespace sol {
|
||||
|
||||
template <typename F, typename = void>
|
||||
struct wrapper {
|
||||
typedef lua_bind_traits<F> traits_type;
|
||||
typedef typename traits_type::args_list args_list;
|
||||
typedef typename traits_type::args_list free_args_list;
|
||||
typedef typename traits_type::returns_list returns_list;
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static decltype(auto) call(Fx&& fx, Args&&... args) {
|
||||
return fx(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
struct caller {
|
||||
template <typename Fx, typename... Args>
|
||||
decltype(auto) operator()(Fx&& fx, Args&&... args) const {
|
||||
return call(std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
struct wrapper<F, std::enable_if_t<std::is_function<meta::unqualified_t<std::remove_pointer_t<F>>>::value>> {
|
||||
typedef lua_bind_traits<F> traits_type;
|
||||
typedef typename traits_type::args_list args_list;
|
||||
typedef typename traits_type::args_list free_args_list;
|
||||
typedef typename traits_type::returns_list returns_list;
|
||||
|
||||
template <F fx, typename... Args>
|
||||
static decltype(auto) invoke(Args&&... args) {
|
||||
return fx(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static decltype(auto) call(Fx&& fx, Args&&... args) {
|
||||
return fx(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
struct caller {
|
||||
template <typename Fx, typename... Args>
|
||||
decltype(auto) operator()(Fx&& fx, Args&&... args) const {
|
||||
return call(std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
struct wrapper<F, std::enable_if_t<std::is_member_object_pointer<meta::unqualified_t<F>>::value>> {
|
||||
typedef lua_bind_traits<F> traits_type;
|
||||
typedef typename traits_type::object_type object_type;
|
||||
typedef typename traits_type::return_type return_type;
|
||||
typedef typename traits_type::args_list args_list;
|
||||
typedef types<object_type&, return_type> free_args_list;
|
||||
typedef typename traits_type::returns_list returns_list;
|
||||
|
||||
template <F fx, typename... Args>
|
||||
static decltype(auto) invoke(object_type& mem, Args&&... args) {
|
||||
return (mem.*fx)(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx>
|
||||
static decltype(auto) call(Fx&& fx, object_type& mem) {
|
||||
return (mem.*fx);
|
||||
}
|
||||
|
||||
template <typename Fx, typename Arg, typename... Args>
|
||||
static void call(Fx&& fx, object_type& mem, Arg&& arg, Args&&... args) {
|
||||
(mem.*fx) = std::forward<Arg>(arg);
|
||||
}
|
||||
|
||||
struct caller {
|
||||
template <typename Fx, typename... Args>
|
||||
decltype(auto) operator()(Fx&& fx, object_type& mem, Args&&... args) const {
|
||||
return call(std::forward<Fx>(fx), mem, std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <typename F, typename R, typename O, typename... FArgs>
|
||||
struct member_function_wrapper {
|
||||
typedef O object_type;
|
||||
typedef lua_bind_traits<F> traits_type;
|
||||
typedef typename traits_type::args_list args_list;
|
||||
typedef types<object_type&, FArgs...> free_args_list;
|
||||
typedef meta::tuple_types<R> returns_list;
|
||||
|
||||
template <F fx, typename... Args>
|
||||
static R invoke(O& mem, Args... args) {
|
||||
return (mem.*fx)(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static R call(Fx&& fx, O& mem, Args... args) {
|
||||
return (mem.*fx)(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
struct caller {
|
||||
template <typename Fx, typename... Args>
|
||||
decltype(auto) operator()(Fx&& fx, O& mem, Args&&... args) const {
|
||||
return call(std::forward<Fx>(fx), mem, std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <typename R, typename O, typename... Args>
|
||||
struct wrapper<R(O:: *)(Args...)> : public member_function_wrapper<R(O:: *)(Args...), R, O, Args...> {
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename O, typename... Args>
|
||||
struct wrapper<R(O:: *)(Args...) const> : public member_function_wrapper<R(O:: *)(Args...) const, R, O, Args...> {
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename O, typename... Args>
|
||||
struct wrapper<R(O:: *)(Args...) const volatile> : public member_function_wrapper<R(O:: *)(Args...) const volatile, R, O, Args...> {
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename O, typename... Args>
|
||||
struct wrapper<R(O:: *)(Args...) &> : public member_function_wrapper<R(O:: *)(Args...) &, R, O, Args...> {
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename O, typename... Args>
|
||||
struct wrapper<R(O:: *)(Args...) const &> : public member_function_wrapper<R(O:: *)(Args...) const &, R, O, Args...> {
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename O, typename... Args>
|
||||
struct wrapper<R(O:: *)(Args...) const volatile &> : public member_function_wrapper<R(O:: *)(Args...) const volatile &, R, O, Args...> {
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename O, typename... Args>
|
||||
struct wrapper<R(O:: *)(Args..., ...) &> : public member_function_wrapper<R(O:: *)(Args..., ...) &, R, O, Args...> {
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename O, typename... Args>
|
||||
struct wrapper<R(O:: *)(Args..., ...) const &> : public member_function_wrapper<R(O:: *)(Args..., ...) const &, R, O, Args...> {
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename O, typename... Args>
|
||||
struct wrapper<R(O:: *)(Args..., ...) const volatile &> : public member_function_wrapper<R(O:: *)(Args..., ...) const volatile &, R, O, Args...> {
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename O, typename... Args>
|
||||
struct wrapper<R(O:: *)(Args...) && > : public member_function_wrapper<R(O:: *)(Args...) &, R, O, Args...> {
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename O, typename... Args>
|
||||
struct wrapper<R(O:: *)(Args...) const &&> : public member_function_wrapper<R(O:: *)(Args...) const &, R, O, Args...> {
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename O, typename... Args>
|
||||
struct wrapper<R(O:: *)(Args...) const volatile &&> : public member_function_wrapper<R(O:: *)(Args...) const volatile &, R, O, Args...> {
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename O, typename... Args>
|
||||
struct wrapper<R(O:: *)(Args..., ...) && > : public member_function_wrapper<R(O:: *)(Args..., ...) &, R, O, Args...> {
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename O, typename... Args>
|
||||
struct wrapper<R(O:: *)(Args..., ...) const &&> : public member_function_wrapper<R(O:: *)(Args..., ...) const &, R, O, Args...> {
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename O, typename... Args>
|
||||
struct wrapper<R(O:: *)(Args..., ...) const volatile &&> : public member_function_wrapper<R(O:: *)(Args..., ...) const volatile &, R, O, Args...> {
|
||||
|
||||
};
|
||||
|
||||
} // sol
|
||||
|
||||
#endif // SOL_WRAPPER_HPP
|
|
@ -4,7 +4,6 @@
|
|||
#include <sol.hpp>
|
||||
|
||||
// There isn't a single library roundtripping with codecvt works on. We'll do the nitty-gritty of it later...
|
||||
#if 0
|
||||
TEST_CASE("stack/strings", "test that strings can be roundtripped") {
|
||||
sol::state lua;
|
||||
|
||||
|
@ -12,7 +11,9 @@ TEST_CASE("stack/strings", "test that strings can be roundtripped") {
|
|||
static const char16_t utf16str[] = { 0xD83C, 0xDF4C, 0x20, 0x6665, 0x20, 0x46, 0x6F, 0x6F, 0x20, 0xA9, 0x20, 0x62, 0x61, 0x72, 0x20, 0xD834, 0xDF06, 0x20, 0x62, 0x61, 0x7A, 0x20, 0x2603, 0x20, 0x71, 0x75, 0x78, 0x00 };
|
||||
static const char32_t utf32str[] = { 0x1F34C, 0x0020, 0x6665, 0x0020, 0x0046, 0x006F, 0x006F, 0x0020, 0x00A9, 0x0020, 0x0062, 0x0061, 0x0072, 0x0020, 0x1D306, 0x0020, 0x0062, 0x0061, 0x007A, 0x0020, 0x2603, 0x0020, 0x0071, 0x0075, 0x0078, 0x00 };
|
||||
static const wchar_t widestr[] = L"Fuck these shitty compilers";
|
||||
static const char32_t utf32str2[] = U"🕴";
|
||||
|
||||
#if 0
|
||||
lua["utf8"] = utf8str;
|
||||
lua["utf16"] = utf16str;
|
||||
lua["utf32"] = utf32str;
|
||||
|
@ -67,5 +68,5 @@ TEST_CASE("stack/strings", "test that strings can be roundtripped") {
|
|||
REQUIRE(utf16_to_char32 == utf32str[0]);
|
||||
REQUIRE(utf32_to_char32 == utf32str[0]);
|
||||
REQUIRE(wide_to_char32 == utf32str[0]);
|
||||
}
|
||||
#endif // Shit C++
|
||||
}
|
||||
|
|
|
@ -359,7 +359,7 @@ TEST_CASE("state/multi-require", "make sure that requires transfers across hand-
|
|||
|
||||
int val1 = thingy1["modfunc"]();
|
||||
int val2 = thingy2["modfunc"]();
|
||||
int val3 = thingy2["modfunc"]();
|
||||
int val3 = thingy3["modfunc"]();
|
||||
REQUIRE(val1 == 221);
|
||||
REQUIRE(val2 == 221);
|
||||
REQUIRE(val3 == 221);
|
||||
|
|
Loading…
Reference in New Issue
Block a user