mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Fix ability to use call constructors for simple usertypes in a more systematic and thorough fashion (still some missing holes, but unlikely to ever encounter)
Add tests to make sure it never happens again
This commit is contained in:
parent
bc889065dc
commit
a9cfe4b980
|
@ -34,6 +34,8 @@ namespace sol {
|
||||||
namespace function_detail {
|
namespace function_detail {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct class_indicator {};
|
struct class_indicator {};
|
||||||
|
|
||||||
|
struct call_indicator {};
|
||||||
}
|
}
|
||||||
namespace stack {
|
namespace stack {
|
||||||
template<typename... Sigs>
|
template<typename... Sigs>
|
||||||
|
@ -237,13 +239,13 @@ namespace sol {
|
||||||
template<typename... Functions>
|
template<typename... Functions>
|
||||||
struct pusher<overload_set<Functions...>> {
|
struct pusher<overload_set<Functions...>> {
|
||||||
static int push(lua_State* L, overload_set<Functions...>&& set) {
|
static int push(lua_State* L, overload_set<Functions...>&& set) {
|
||||||
typedef function_detail::overloaded_function<Functions...> F;
|
typedef function_detail::overloaded_function<0, Functions...> F;
|
||||||
pusher<function_sig<>>{}.set_fx<F>(L, std::move(set.functions));
|
pusher<function_sig<>>{}.set_fx<F>(L, std::move(set.functions));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, const overload_set<Functions...>& set) {
|
static int push(lua_State* L, const overload_set<Functions...>& set) {
|
||||||
typedef function_detail::overloaded_function<Functions...> F;
|
typedef function_detail::overloaded_function<0, Functions...> F;
|
||||||
pusher<function_sig<>>{}.set_fx<F>(L, set.functions);
|
pusher<function_sig<>>{}.set_fx<F>(L, set.functions);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -307,16 +309,28 @@ namespace sol {
|
||||||
template <typename... Functions>
|
template <typename... Functions>
|
||||||
struct pusher<factory_wrapper<Functions...>> {
|
struct pusher<factory_wrapper<Functions...>> {
|
||||||
static int push(lua_State* L, const factory_wrapper<Functions...>& fw) {
|
static int push(lua_State* L, const factory_wrapper<Functions...>& fw) {
|
||||||
typedef function_detail::overloaded_function<Functions...> F;
|
typedef function_detail::overloaded_function<0, Functions...> F;
|
||||||
pusher<function_sig<>>{}.set_fx<F>(L, fw.functions);
|
pusher<function_sig<>>{}.set_fx<F>(L, fw.functions);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, factory_wrapper<Functions...>&& fw) {
|
static int push(lua_State* L, factory_wrapper<Functions...>&& fw) {
|
||||||
typedef function_detail::overloaded_function<Functions...> F;
|
typedef function_detail::overloaded_function<0, Functions...> F;
|
||||||
pusher<function_sig<>>{}.set_fx<F>(L, std::move(fw.functions));
|
pusher<function_sig<>>{}.set_fx<F>(L, std::move(fw.functions));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, const factory_wrapper<Functions...>& set, function_detail::call_indicator) {
|
||||||
|
typedef function_detail::overloaded_function<1, Functions...> F;
|
||||||
|
pusher<function_sig<>>{}.set_fx<F>(L, set.functions);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, factory_wrapper<Functions...>&& set, function_detail::call_indicator) {
|
||||||
|
typedef function_detail::overloaded_function<1, Functions...> F;
|
||||||
|
pusher<function_sig<>>{}.set_fx<F>(L, std::move(set.functions));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename... Lists>
|
template <typename T, typename... Lists>
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
namespace function_detail {
|
namespace function_detail {
|
||||||
template <typename... Functions>
|
template <int start_skew = 0, typename... Functions>
|
||||||
struct overloaded_function {
|
struct overloaded_function {
|
||||||
typedef std::tuple<Functions...> overload_list;
|
typedef std::tuple<Functions...> overload_list;
|
||||||
typedef std::make_index_sequence<sizeof...(Functions)> indices;
|
typedef std::make_index_sequence<sizeof...(Functions)> indices;
|
||||||
|
@ -50,7 +50,7 @@ namespace sol {
|
||||||
|
|
||||||
int operator()(lua_State* L) {
|
int operator()(lua_State* L) {
|
||||||
auto mfx = [&](auto&&... args) { return this->call(std::forward<decltype(args)>(args)...); };
|
auto mfx = [&](auto&&... args) { return this->call(std::forward<decltype(args)>(args)...); };
|
||||||
return call_detail::overload_match<Functions...>(mfx, L, 1);
|
return call_detail::overload_match<Functions...>(mfx, L, 1 + start_skew);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // function_detail
|
} // function_detail
|
||||||
|
|
|
@ -208,19 +208,31 @@ namespace sol {
|
||||||
hint->second = std::move(o);
|
hint->second = std::move(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename N, typename F, typename... Args>
|
||||||
|
void insert_prepare(std::true_type, lua_State* L, N&& n, F&& f, Args&&... args) {
|
||||||
|
object o = make_object<F>(L, std::forward<F>(f), function_detail::call_indicator(), std::forward<Args>(args)...);
|
||||||
|
callconstructfunc = std::move(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename N, typename F, typename... Args>
|
||||||
|
void insert_prepare(std::false_type, lua_State* L, N&& n, F&& f, Args&&... args) {
|
||||||
|
object o = make_object<F>(L, std::forward<F>(f), std::forward<Args>(args)...);
|
||||||
|
insert(std::forward<N>(n), std::move(o));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename N, typename F>
|
template <typename N, typename F>
|
||||||
void add_member_function(std::true_type, lua_State* L, N&& n, F&& f) {
|
void add_member_function(std::true_type, lua_State* L, N&& n, F&& f) {
|
||||||
object o = make_object<F>(L, std::forward<F>(f), function_detail::class_indicator<T>());
|
insert_prepare(std::is_same<meta::unqualified_t<N>, call_construction>(), L, std::forward<N>(n), std::forward<F>(f), function_detail::class_indicator<T>());
|
||||||
if (std::is_same<meta::unqualified_t<N>, call_construction>::value) {
|
|
||||||
callconstructfunc = std::move(o);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
insert(std::forward<N>(n), std::move(o));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename N, typename F>
|
template <typename N, typename F>
|
||||||
void add_member_function(std::false_type, lua_State* L, N&& n, F&& f) {
|
void add_member_function(std::false_type, lua_State* L, N&& n, F&& f) {
|
||||||
object o = make_object<F>(L, std::forward<F>(f));
|
insert_prepare(std::is_same<meta::unqualified_t<N>, call_construction>(), L, std::forward<N>(n), std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename N, typename F, meta::enable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler>
|
||||||
|
void add_function(lua_State* L, N&& n, F&& f) {
|
||||||
|
object o = make_object(L, as_function_reference(std::forward<F>(f)));
|
||||||
if (std::is_same<meta::unqualified_t<N>, call_construction>::value) {
|
if (std::is_same<meta::unqualified_t<N>, call_construction>::value) {
|
||||||
callconstructfunc = std::move(o);
|
callconstructfunc = std::move(o);
|
||||||
return;
|
return;
|
||||||
|
@ -228,11 +240,6 @@ namespace sol {
|
||||||
insert(std::forward<N>(n), std::move(o));
|
insert(std::forward<N>(n), std::move(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename N, typename F, meta::enable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler>
|
|
||||||
void add_function(lua_State* L, N&& n, F&& f) {
|
|
||||||
insert(std::forward<N>(n), make_object(L, as_function_reference(std::forward<F>(f))));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename N, typename F, meta::disable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler>
|
template <typename N, typename F, meta::disable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler>
|
||||||
void add_function(lua_State* L, N&& n, F&& f) {
|
void add_function(lua_State* L, N&& n, F&& f) {
|
||||||
add_member_function(std::is_member_pointer<meta::unwrap_unqualified_t<F>>(), L, std::forward<N>(n), std::forward<F>(f));
|
add_member_function(std::is_member_pointer<meta::unwrap_unqualified_t<F>>(), L, std::forward<N>(n), std::forward<F>(f));
|
||||||
|
|
|
@ -487,3 +487,52 @@ TEST_CASE("usertype/simple-class-propogation", "make sure methods and variables
|
||||||
b:thing()
|
b:thing()
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/simple-call-constructor", "ensure that all kinds of call-based constructors can be serialized") {
|
||||||
|
struct f_test {
|
||||||
|
int i; f_test(int i) : i(i) {}
|
||||||
|
};
|
||||||
|
struct i_test {
|
||||||
|
int i; i_test(int i) : i(i) {}
|
||||||
|
};
|
||||||
|
struct r_test {
|
||||||
|
int i; r_test(int i) : i(i) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
auto f = sol::factories([]() {return f_test(30); });
|
||||||
|
|
||||||
|
lua.new_simple_usertype<f_test>("f_test",
|
||||||
|
sol::call_constructor, sol::factories([]() {
|
||||||
|
return f_test(20);
|
||||||
|
}),
|
||||||
|
"new", f
|
||||||
|
);
|
||||||
|
|
||||||
|
lua.new_simple_usertype<i_test>("i_test",
|
||||||
|
sol::call_constructor, sol::initializers([](i_test& obj) {
|
||||||
|
new(&obj)i_test(21);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
lua.new_simple_usertype<r_test>("r_test",
|
||||||
|
sol::call_constructor, [](sol::table t) {
|
||||||
|
return r_test(22);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
lua.script("a = f_test()");
|
||||||
|
lua.script("b = i_test()");
|
||||||
|
lua.script("c = r_test()");
|
||||||
|
lua.script("d = f_test.new()");
|
||||||
|
f_test& a = lua["a"];
|
||||||
|
f_test& d = lua["d"];
|
||||||
|
i_test& b = lua["b"];
|
||||||
|
r_test& c = lua["c"];
|
||||||
|
REQUIRE(a.i == 20);
|
||||||
|
REQUIRE(b.i == 21);
|
||||||
|
REQUIRE(c.i == 22);
|
||||||
|
REQUIRE(d.i == 30);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user