mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Proper std::ref semantics throughout the codebase's get/set.
Also a convenience type `sol::ref`, which is just an alias to `std::reference_wrapper`, to enable easy getting with `lua.get<>` (we can't use `lua.get<some_type>` because of necessary `Unqualified<T>` use)
This commit is contained in:
parent
ad83552072
commit
6121da334f
|
@ -127,6 +127,22 @@ struct getter<T*> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct getter<T&> {
|
||||||
|
static T& get(lua_State* L, int index = -1) {
|
||||||
|
void* udata = lua_touserdata(L, index);
|
||||||
|
T** obj = static_cast<T**>(udata);
|
||||||
|
return **obj;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct getter<std::reference_wrapper<T>> {
|
||||||
|
static T& get(lua_State* L, int index = -1) {
|
||||||
|
return getter<T&>{}.get(L, index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct getter<type> {
|
struct getter<type> {
|
||||||
static type get(lua_State *L, int index){
|
static type get(lua_State *L, int index){
|
||||||
|
@ -243,7 +259,7 @@ struct pusher {
|
||||||
|
|
||||||
template<typename U = Unqualified<T>, EnableIf<Not<has_begin_end<U>>, Not<std::is_base_of<reference, U>>, Not<std::is_integral<U>>, Not<std::is_floating_point<U>>> = 0>
|
template<typename U = Unqualified<T>, EnableIf<Not<has_begin_end<U>>, Not<std::is_base_of<reference, U>>, Not<std::is_integral<U>>, Not<std::is_floating_point<U>>> = 0>
|
||||||
static void push(lua_State* L, T& t) {
|
static void push(lua_State* L, T& t) {
|
||||||
pusher<T*>{}.push(L, std::addressof(t));
|
detail::push_userdata<U>(L, userdata_traits<T>::metatable, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U = Unqualified<T>, EnableIf<Not<has_begin_end<U>>, Not<std::is_base_of<reference, U>>, Not<std::is_integral<U>>, Not<std::is_floating_point<U>>> = 0>
|
template<typename U = Unqualified<T>, EnableIf<Not<has_begin_end<U>>, Not<std::is_base_of<reference, U>>, Not<std::is_integral<U>>, Not<std::is_floating_point<U>>> = 0>
|
||||||
|
@ -259,6 +275,13 @@ struct pusher<T*> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct pusher<std::reference_wrapper<T>> {
|
||||||
|
static void push(lua_State* L, const std::reference_wrapper<T>& t) {
|
||||||
|
pusher<T*>{}.push(L, std::addressof(t.get()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct pusher<bool> {
|
struct pusher<bool> {
|
||||||
static void push(lua_State* L, const bool& b) {
|
static void push(lua_State* L, const bool& b) {
|
||||||
|
|
|
@ -93,6 +93,9 @@ struct constructors {};
|
||||||
|
|
||||||
const auto default_constructor = constructors<types<>>{};
|
const auto default_constructor = constructors<types<>>{};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using ref = std::reference_wrapper<T>;
|
||||||
|
|
||||||
} // sol
|
} // sol
|
||||||
|
|
||||||
#endif // SOL_TUPLE_HPP
|
#endif // SOL_TUPLE_HPP
|
||||||
|
|
40
tests.cpp
40
tests.cpp
|
@ -84,6 +84,18 @@ struct self_test {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct vars {
|
||||||
|
vars () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int boop = 0;
|
||||||
|
|
||||||
|
~vars () {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct object {
|
struct object {
|
||||||
std::string operator() () {
|
std::string operator() () {
|
||||||
std::cout << "member_test()" << std::endl;
|
std::cout << "member_test()" << std::endl;
|
||||||
|
@ -469,7 +481,7 @@ TEST_CASE("functions/return_order_and_multi_get", "Check if return order is in t
|
||||||
auto tluaget = lua.get<int, int, int>("x", "y", "z");
|
auto tluaget = lua.get<int, int, int>("x", "y", "z");
|
||||||
std::cout << "cpp: " << std::get<0>(tcpp) << ',' << std::get<1>(tcpp) << ',' << std::get<2>(tcpp) << std::endl;
|
std::cout << "cpp: " << std::get<0>(tcpp) << ',' << std::get<1>(tcpp) << ',' << std::get<2>(tcpp) << std::endl;
|
||||||
std::cout << "lua: " << std::get<0>(tlua) << ',' << std::get<1>(tlua) << ',' << std::get<2>(tlua) << std::endl;
|
std::cout << "lua: " << std::get<0>(tlua) << ',' << std::get<1>(tlua) << ',' << std::get<2>(tlua) << std::endl;
|
||||||
std::cout << "lua.xyz: " << lua.get<int>("x") << ',' << lua.get<int>("y") << ',' << lua.get<int>("z") << std::endl;
|
std::cout << "lua xyz: " << lua.get<int>("x") << ',' << lua.get<int>("y") << ',' << lua.get<int>("z") << std::endl;
|
||||||
REQUIRE(tcpp == triple);
|
REQUIRE(tcpp == triple);
|
||||||
REQUIRE(tlua == triple);
|
REQUIRE(tlua == triple);
|
||||||
REQUIRE(tluaget == triple);
|
REQUIRE(tluaget == triple);
|
||||||
|
@ -857,10 +869,6 @@ TEST_CASE("userdata/nonmember functions implement functionality", "let users set
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("regressions/one", "issue number 48") {
|
TEST_CASE("regressions/one", "issue number 48") {
|
||||||
struct vars {
|
|
||||||
int boop = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
lua.new_userdata<vars>("vars", "boop", &vars::boop);
|
lua.new_userdata<vars>("vars", "boop", &vars::boop);
|
||||||
REQUIRE_NOTHROW(lua.script("beep = vars.new()\n"
|
REQUIRE_NOTHROW(lua.script("beep = vars.new()\n"
|
||||||
|
@ -871,3 +879,25 @@ TEST_CASE("regressions/one", "issue number 48") {
|
||||||
auto* ptr = &my_var;
|
auto* ptr = &my_var;
|
||||||
REQUIRE(ptr->boop == 1);
|
REQUIRE(ptr->boop == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("references/get-set", "properly get and set with std::ref semantics. Note that to get, we must not use Unqualified<T> on the type...") {
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
lua.new_userdata<vars>("vars",
|
||||||
|
"boop", &vars::boop);
|
||||||
|
|
||||||
|
vars var{};
|
||||||
|
vars rvar{};
|
||||||
|
lua.set("beep", var);
|
||||||
|
lua.set("rbeep", std::ref(rvar));
|
||||||
|
auto& my_var = lua.get<vars>("beep");
|
||||||
|
auto& ref_var = lua.get<sol::ref<vars>>("rbeep");
|
||||||
|
|
||||||
|
var.boop = 2;
|
||||||
|
rvar.boop = 5;
|
||||||
|
|
||||||
|
REQUIRE((my_var.boop == 0));
|
||||||
|
REQUIRE(var.boop != my_var.boop);
|
||||||
|
// Reference should point back to the same type.
|
||||||
|
REQUIRE(rvar.boop == ref_var.boop);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user