mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Fixed usertype checking for overloading resolution (and for userdata in general)
This commit is contained in:
parent
427194bc92
commit
a71c9737d4
|
@ -64,7 +64,7 @@ struct overloaded_function : base_function {
|
||||||
if (!detail::check_types(args_type(), args_type(), L)) {
|
if (!detail::check_types(args_type(), args_type(), L)) {
|
||||||
return match_arity(L, x, indices<In...>());
|
return match_arity(L, x, indices<In...>());
|
||||||
}
|
}
|
||||||
return stack::typed_call(return_type(), args_type(), func, L);
|
return stack::typed_call<false>(return_type(), args_type(), func, L);
|
||||||
}
|
}
|
||||||
|
|
||||||
int match_arity(lua_State* L) {
|
int match_arity(lua_State* L) {
|
||||||
|
@ -120,7 +120,7 @@ struct usertype_overloaded_function : base_function {
|
||||||
return match_arity(L, x, indices<In...>());
|
return match_arity(L, x, indices<In...>());
|
||||||
}
|
}
|
||||||
func.item = ptr(stack::get<T>(L, 1));
|
func.item = ptr(stack::get<T>(L, 1));
|
||||||
return stack::typed_call(return_type(), args_type(), func, L);
|
return stack::typed_call<false>(return_type(), args_type(), func, L);
|
||||||
}
|
}
|
||||||
|
|
||||||
int match_arity(lua_State* L) {
|
int match_arity(lua_State* L) {
|
||||||
|
@ -175,7 +175,7 @@ struct usertype_indexing_function<overload_set<Functions...>, T> : base_function
|
||||||
return match_arity(L, x, indices<In...>());
|
return match_arity(L, x, indices<In...>());
|
||||||
}
|
}
|
||||||
func.item = ptr(stack::get<T>(L, 1));
|
func.item = ptr(stack::get<T>(L, 1));
|
||||||
return stack::typed_call(return_type(), args_type(), func, L);
|
return stack::typed_call<false>(return_type(), args_type(), func, L);
|
||||||
}
|
}
|
||||||
|
|
||||||
int match_arity(lua_State* L) {
|
int match_arity(lua_State* L) {
|
||||||
|
|
|
@ -203,18 +203,46 @@ struct checker {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, type expected, typename C>
|
template <typename T, typename C>
|
||||||
struct checker<T*, expected, C> {
|
struct checker<T*, type::userdata, C> {
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static bool check (lua_State* L, int index, const Handler& handler) {
|
static bool check (lua_State* L, int index, const Handler& handler) {
|
||||||
const type indextype = type_of(L, index);
|
const type indextype = type_of(L, index);
|
||||||
// Allow nil to be transformed to nullptr
|
// Allow nil to be transformed to nullptr
|
||||||
bool success = expected == indextype || indextype == type::nil;
|
if (indextype == type::nil) {
|
||||||
if (!success) {
|
return true;
|
||||||
// expected type, actual type
|
|
||||||
handler(L, index, expected, indextype);
|
|
||||||
}
|
}
|
||||||
return success;
|
return checker<T, type::userdata, C>{}.check(L, indextype, index, handler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T,typename C>
|
||||||
|
struct checker<T, type::userdata, C> {
|
||||||
|
template <typename Handler>
|
||||||
|
static bool check (lua_State* L, type indextype, int index, const Handler& handler) {
|
||||||
|
if (indextype != type::userdata) {
|
||||||
|
handler(L, index, type::userdata, indextype);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (lua_getmetatable(L, index) == 0) {
|
||||||
|
handler(L, index, type::userdata, indextype);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const type expectedmetatabletype = static_cast<type>(luaL_getmetatable(L, &usertype_traits<T>::metatable[0]));
|
||||||
|
if (expectedmetatabletype == type::nil) {
|
||||||
|
lua_pop(L, 2);
|
||||||
|
handler(L, index, type::userdata, indextype);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool success = lua_rawequal(L, -1, -2) == 1;
|
||||||
|
lua_pop(L, 2);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Handler>
|
||||||
|
static bool check (lua_State* L, int index, const Handler& handler) {
|
||||||
|
const type indextype = type_of(L, index);
|
||||||
|
return check(L, indextype, index, handler);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -628,17 +656,17 @@ inline void call(lua_State* L, types<void> tr, types<Args...> ta, Fx&& fx, FxArg
|
||||||
call<checkargs>(L, 0, ta, tr, ta, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
call<checkargs>(L, 0, ta, tr, ta, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args, typename Fx>
|
template<bool check_args = detail::default_check_arguments, typename... Args, typename Fx>
|
||||||
inline int typed_call(types<void> tr, types<Args...> ta, Fx&& fx, lua_State* L) {
|
inline int typed_call(types<void> tr, types<Args...> ta, Fx&& fx, lua_State* L) {
|
||||||
stack::call(L, 0, tr, ta, fx);
|
stack::call<check_args>(L, 0, tr, ta, fx);
|
||||||
int nargs = static_cast<int>(sizeof...(Args));
|
int nargs = static_cast<int>(sizeof...(Args));
|
||||||
lua_pop(L, nargs);
|
lua_pop(L, nargs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Ret, typename... Args, typename Fx>
|
template<bool check_args = detail::default_check_arguments, typename... Ret, typename... Args, typename Fx>
|
||||||
inline int typed_call(types<Ret...> tr, types<Args...> ta, Fx&& fx, lua_State* L) {
|
inline int typed_call(types<Ret...> tr, types<Args...> ta, Fx&& fx, lua_State* L) {
|
||||||
decltype(auto) r = stack::call(L, 0, tr, ta, fx);
|
decltype(auto) r = stack::call<check_args>(L, 0, tr, ta, fx);
|
||||||
int nargs = static_cast<int>(sizeof...(Args));
|
int nargs = static_cast<int>(sizeof...(Args));
|
||||||
lua_pop(L, nargs);
|
lua_pop(L, nargs);
|
||||||
return stack::push(L, std::forward<decltype(r)>(r));
|
return stack::push(L, std::forward<decltype(r)>(r));
|
||||||
|
|
Loading…
Reference in New Issue
Block a user