diff --git a/sol/proxy.hpp b/sol/proxy.hpp
index d8324ef0..85e7e6c3 100644
--- a/sol/proxy.hpp
+++ b/sol/proxy.hpp
@@ -117,10 +117,9 @@ inline bool operator!=(const proxy
& right, T&& left) {
namespace stack {
template
struct pusher> {
- static int push (lua_State* L, const proxy& p) {
- stack::push(L, p.tbl);
- int tblindex = lua_gettop(L);
- stack::get_field, global_table>::value>(L, p.key, tblindex);
+ static int push (lua_State*, const proxy& p) {
+ sol::reference r = p;
+ r.push();
return 1;
}
};
diff --git a/sol/stack.hpp b/sol/stack.hpp
index f50345c3..d0b0618d 100644
--- a/sol/stack.hpp
+++ b/sol/stack.hpp
@@ -127,8 +127,22 @@ true;
false;
#endif
+template
+inline bool check_metatable(lua_State* L, int index = -2) {
+ luaL_getmetatable(L, &usertype_traits::metatable[0]);
+ const type expectedmetatabletype = get(L);
+ if (expectedmetatabletype != type::nil) {
+ if (lua_rawequal(L, -1, index) == 1) {
+ lua_pop(L, 2);
+ return true;
+ }
+ }
+ lua_pop(L, 1);
+ return false;
+}
+
template
-static int push_upvalues(lua_State* L, TCont&& cont) {
+inline int push_upvalues(lua_State* L, TCont&& cont) {
int n = 0;
for(auto& c : cont) {
if(releasemem) {
@@ -411,7 +425,7 @@ struct checker {
if (indextype == type::nil) {
return true;
}
- return checker{}.check(types(), L, indextype, index, handler);
+ return checker{}.check(types(), L, indextype, index, handler);
}
};
@@ -428,16 +442,13 @@ struct checker {
if (lua_getmetatable(L, index) == 0) {
handler(L, index, type::userdata, indextype);
return false;
- }
- luaL_getmetatable(L, &usertype_traits::metatable[0]);
- const type expectedmetatabletype = get(L);
- if (expectedmetatabletype != type::nil) {
- if (lua_rawequal(L, -1, -2) == 1) {
- lua_pop(L, 2);
- return true;
- }
- }
- lua_pop(L, 1);
+ }
+ if (stack_detail::check_metatable(L))
+ return true;
+ if (stack_detail::check_metatable(L))
+ return true;
+ if (stack_detail::check_metatable>(L))
+ return true;
#ifndef SOL_NO_EXCEPTIONS
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
void* basecastdata = stack::get(L);
diff --git a/tests_coroutines.cpp b/test_coroutines.cpp
similarity index 100%
rename from tests_coroutines.cpp
rename to test_coroutines.cpp
diff --git a/test_functions.cpp b/test_functions.cpp
new file mode 100644
index 00000000..51a75157
--- /dev/null
+++ b/test_functions.cpp
@@ -0,0 +1,329 @@
+#define SOL_CHECK_ARGUMENTS
+
+#include
+#include
+#include
+
+std::function makefn() {
+ auto fx = []() -> int {
+ return 0x1456789;
+ };
+ return fx;
+}
+
+void takefn(std::function purr) {
+ if (purr() != 0x1456789)
+ throw 0;
+}
+
+struct A {
+ int a = 0xA; int bark() { return 1; }
+};
+
+std::tuple bark(int num_value, A* a) {
+ return std::tuple(num_value * 2, a->bark());
+}
+
+void test_free_func(std::function f) {
+ f();
+}
+
+void test_free_func2(std::function f, int arg1) {
+ int val = f(arg1);
+ if(val != arg1)
+ throw sol::error("failed function call!");
+}
+
+int overloaded(int x) {
+ std::cout << x << std::endl;
+ return 3;
+}
+
+int overloaded(int x, int y) {
+ std::cout << x << " " << y << std::endl;
+ return 7;
+}
+
+int overloaded(int x, int y, int z) {
+ std::cout << x << " " << y << " " << z << std::endl;
+ return 11;
+}
+
+int non_overloaded(int x, int y, int z) {
+ std::cout << x << " " << y << " " << z << std::endl;
+ return 13;
+}
+
+TEST_CASE("functions/overload-resolution", "Check if overloaded function resolution templates compile/work") {
+ sol::state lua;
+ lua.open_libraries(sol::lib::base);
+
+ lua.set_function("non_overloaded", non_overloaded);
+ REQUIRE_NOTHROW(lua.script("x = non_overloaded(1, 2, 3)\nprint(x)"));
+
+ /*
+ // Cannot reasonably support: clang++ refuses to try enough
+ // deductions to make this work
+ lua.set_function("overloaded", overloaded);
+ REQUIRE_NOTHROW(lua.script("print(overloaded(1))"));
+
+ lua.set_function("overloaded", overloaded);
+ REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2))"));
+
+ lua.set_function("overloaded", overloaded);
+ REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2, 3))"));
+ */
+ lua.set_function("overloaded", overloaded);
+ REQUIRE_NOTHROW(lua.script("print(overloaded(1))"));
+
+ lua.set_function("overloaded", overloaded);
+ REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2))"));
+
+ lua.set_function("overloaded", overloaded);
+ REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2, 3))"));
+}
+
+TEST_CASE("functions/return-order-and-multi-get", "Check if return order is in the same reading order specified in Lua") {
+ const static std::tuple triple = std::make_tuple(10, 11, 12);
+ const static std::tuple paired = std::make_tuple(10, 10.f);
+ sol::state lua;
+ lua.set_function("f", [] {
+ return std::make_tuple(10, 11, 12);
+ } );
+ int a = 0;
+ lua.set_function( "h", []() {
+ return std::make_tuple( 10, 10.0f );
+ } );
+ lua.script("function g() return 10, 11, 12 end\nx,y,z = g()");
+ auto tcpp = lua.get("f").call();
+ auto tlua = lua.get( "g" ).call();
+ auto tcpp2 = lua.get( "h" ).call();
+ auto tluaget = lua.get( "x", "y", "z" );
+ REQUIRE(tcpp == triple);
+ REQUIRE(tlua == triple);
+ REQUIRE(tluaget == triple);
+ REQUIRE(tcpp2 == paired);
+}
+
+TEST_CASE("functions/deducing-return-order-and-multi-get", "Check if return order is in the same reading order specified in Lua, with regular deducing calls") {
+ const static std::tuple triple = std::make_tuple(10, 11, 12);
+ sol::state lua;
+ lua.set_function( "f_string", []() { return "this is a string!"; } );
+ sol::function f_string = lua[ "f_string" ];
+
+ // Make sure there are no overload collisions / compiler errors for automatic string conversions
+ std::string f_string_result = f_string();
+ REQUIRE(f_string_result == "this is a string!");
+ f_string_result = f_string();
+ REQUIRE(f_string_result == "this is a string!");
+
+ lua.set_function("f", [] {
+ return std::make_tuple(10, 11, 12);
+ });
+ lua.script("function g() return 10, 11, 12 end\nx,y,z = g()");
+ std::tuple tcpp = lua.get("f")();
+ std::tuple tlua = lua.get("g")();
+ std::tuple tluaget = lua.get("x", "y", "z");
+ 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 xyz: " << lua.get("x") << ',' << lua.get("y") << ',' << lua.get("z") << std::endl;
+ REQUIRE(tcpp == triple);
+ REQUIRE(tlua == triple);
+ REQUIRE(tluaget == triple);
+}
+
+TEST_CASE("functions/pair-and-tuple-and-proxy-tests", "Check if sol::reference and sol::proxy can be passed to functions as arguments") {
+ sol::state lua;
+ lua.new_usertype("A",
+ "bark", &A::bark);
+ lua.script(R"( function f (num_value, a)
+ return num_value * 2, a:bark()
+end
+nested = { variables = { no = { problem = 10 } } } )");
+ lua.set_function("g", bark);
+
+ sol::function cpp_bark = lua["g"];
+ sol::function lua_bark = lua["f"];
+
+ sol::reference lua_variable_x = lua["nested"]["variables"]["no"]["problem"];
+ A cpp_variable_y;
+
+ std::tuple ab = cpp_bark(lua_variable_x, cpp_variable_y);
+ std::pair cd = lua_bark(lua["nested"]["variables"]["no"]["problem"], cpp_variable_y);
+
+ static const std::tuple abdesired( 20, 1 );
+ static const std::pair cddesired = { 20, 1 };
+ REQUIRE(ab == abdesired);
+ REQUIRE(cd == cddesired);
+}
+
+TEST_CASE("functions/sol::function-to-std::function", "check if conversion to std::function works properly and calls with correct arguments") {
+ sol::state lua;
+ lua.open_libraries(sol::lib::base);
+
+ lua.set_function("testFunc", test_free_func);
+ lua.set_function("testFunc2", test_free_func2);
+ lua.script(
+ "testFunc(function() print(\"hello std::function\") end)"
+ );
+ lua.script(
+ "function m(a)\n"
+ " print(\"hello std::function with arg \", a)\n"
+ " return a\n"
+ "end\n"
+ "\n"
+ "testFunc2(m, 1)"
+ );
+}
+
+TEST_CASE("functions/returning-functions-from-C++-and-gettin-in-lua", "check to see if returning a functor and getting a functor from lua is possible") {
+ sol::state lua;
+ lua.open_libraries(sol::lib::base);
+
+ lua.set_function("makefn", makefn);
+ lua.set_function("takefn", takefn);
+ lua.script("afx = makefn()\n"
+ "print(afx())\n"
+ "takefn(afx)\n");
+}
+
+TEST_CASE( "functions/function_result-protected_function_result", "Function result should be the beefy return type for sol::function that allows for error checking and error handlers" ) {
+ sol::state lua;
+ lua.open_libraries( sol::lib::base, sol::lib::debug );
+ static const char unhandlederrormessage[] = "true error message";
+ static const char handlederrormessage[] = "doodle";
+
+ // Some function; just using a lambda to be cheap
+ auto doomfx = []() {
+ std::cout << "doomfx called" << std::endl;
+ throw std::runtime_error( unhandlederrormessage );
+ };
+ auto luadoomfx = [&lua]() {
+ std::cout << "luadoomfx called" << std::endl;
+ // Does not bypass error function, will call it
+ luaL_error( lua.lua_state(), unhandlederrormessage );
+ };
+ lua.set_function("doom", doomfx);
+ lua.set_function("luadoom", luadoomfx);
+
+ auto cpphandlerfx = []( std::string x ) {
+ std::cout << "c++ handler called with: " << x << std::endl;
+ return handlederrormessage;
+ };
+ lua.set_function( "cpphandler", cpphandlerfx );
+ lua.script(
+ std::string( "function luahandler ( message )" )
+ + " print('lua handler called with: ' .. message)"
+ + " return '" + handlederrormessage + "'"
+ + "end"
+ );
+ auto nontrampolinefx = [](lua_State*) -> int { throw "x";};
+ lua_CFunction c_nontrampolinefx = nontrampolinefx;
+ lua.set("nontrampoline", c_nontrampolinefx);
+
+ sol::protected_function doom = lua[ "doom" ];
+ sol::protected_function luadoom = lua["luadoom"];
+ sol::protected_function nontrampoline = lua["nontrampoline"];
+ sol::function luahandler = lua["luahandler"];
+ sol::function cpphandler = lua[ "cpphandler" ];
+ doom.error_handler = luahandler;
+ luadoom.error_handler = cpphandler;
+ nontrampoline.error_handler = cpphandler;
+
+ {
+ sol::protected_function_result result = doom();
+ REQUIRE(!result.valid());
+ std::string errorstring = result;
+ REQUIRE(errorstring == handlederrormessage);
+ }
+ {
+ sol::protected_function_result result = luadoom();
+ REQUIRE(!result.valid());
+ std::string errorstring = result;
+ REQUIRE(errorstring == handlederrormessage);
+ }
+ {
+ sol::protected_function_result result = nontrampoline();
+ REQUIRE(!result.valid());
+ std::string errorstring = result;
+ REQUIRE(errorstring == handlederrormessage);
+ }
+}
+
+TEST_CASE("functions/destructor-tests", "Show that proper copies / destruction happens") {
+ static int created = 0;
+ static int destroyed = 0;
+ static void* last_call = nullptr;
+ static void* static_call = reinterpret_cast(0x01);
+ typedef void(* fptr)();
+ struct x {
+ x() {++created;}
+ x(const x&) {++created;}
+ x(x&&) {++created;}
+ x& operator=(const x&) {return *this;}
+ x& operator=(x&&) {return *this;}
+ void func() {last_call = static_cast(this);};
+ ~x () {++destroyed;}
+ };
+ struct y {
+ y() {++created;}
+ y(const x&) {++created;}
+ y(x&&) {++created;}
+ y& operator=(const x&) {return *this;}
+ y& operator=(x&&) {return *this;}
+ static void func() {last_call = static_call;};
+ void operator()() {func();}
+ operator fptr () { return func; }
+ ~y () {++destroyed;}
+ };
+
+ // stateful functors/member functions should always copy unless specified
+ {
+ created = 0;
+ destroyed = 0;
+ last_call = nullptr;
+ {
+ sol::state lua;
+ x x1;
+ lua.set_function("x1copy", &x::func, x1);
+ lua.script("x1copy()");
+ REQUIRE(created == 2);
+ REQUIRE(destroyed == 0);
+ REQUIRE_FALSE(last_call == &x1);
+
+ lua.set_function("x1ref", &x::func, std::ref(x1));
+ lua.script("x1ref()");
+ REQUIRE(created == 2);
+ REQUIRE(destroyed == 0);
+ REQUIRE(last_call == &x1);
+ }
+ REQUIRE(created == 2);
+ REQUIRE(destroyed == 2);
+ }
+
+ // things convertible to a static function should _never_ be forced to make copies
+ // therefore, pass through untouched
+ {
+ created = 0;
+ destroyed = 0;
+ last_call = nullptr;
+ {
+ sol::state lua;
+ y y1;
+ lua.set_function("y1copy", y1);
+ lua.script("y1copy()");
+ REQUIRE(created == 1);
+ REQUIRE(destroyed == 0);
+ REQUIRE(last_call == static_call);
+
+ last_call = nullptr;
+ lua.set_function("y1ref", std::ref(y1));
+ lua.script("y1ref()");
+ REQUIRE(created == 1);
+ REQUIRE(destroyed == 0);
+ REQUIRE(last_call == static_call);
+ }
+ REQUIRE(created == 1);
+ REQUIRE(destroyed == 1);
+ }
+}
\ No newline at end of file
diff --git a/tests_overflow.cpp b/test_overflow.cpp
similarity index 100%
rename from tests_overflow.cpp
rename to test_overflow.cpp
diff --git a/tests.cpp b/tests.cpp
index dab4afea..acd2048d 100644
--- a/tests.cpp
+++ b/tests.cpp
@@ -16,53 +16,11 @@ struct stack_guard {
~stack_guard() { endtop = lua_gettop(L); }
};
-void test_free_func(std::function f) {
- f();
-}
-
-void test_free_func2(std::function f, int arg1) {
- int val = f(arg1);
- if(val != arg1)
- throw sol::error("failed function call!");
-}
-
-std::function makefn() {
- auto fx = []() -> int {
- return 0x1456789;
- };
- return fx;
-}
-
-void takefn(std::function purr) {
- if (purr() != 0x1456789)
- throw 0;
-}
-
std::string free_function() {
std::cout << "free_function()" << std::endl;
return "test";
}
-int overloaded(int x) {
- std::cout << x << std::endl;
- return 3;
-}
-
-int overloaded(int x, int y) {
- std::cout << x << " " << y << std::endl;
- return 7;
-}
-
-int overloaded(int x, int y, int z) {
- std::cout << x << " " << y << " " << z << std::endl;
- return 11;
-}
-
-int non_overloaded(int x, int y, int z) {
- std::cout << x << " " << y << " " << z << std::endl;
- return 13;
-}
-
std::vector test_table_return_one() {
return { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
}
@@ -609,114 +567,6 @@ TEST_CASE("tables/functions-variables", "Check if tables and function calls work
REQUIRE_NOTHROW(run_script(lua));
}
-TEST_CASE("functions/overload-resolution", "Check if overloaded function resolution templates compile/work") {
- sol::state lua;
- lua.open_libraries(sol::lib::base);
-
- lua.set_function("non_overloaded", non_overloaded);
- REQUIRE_NOTHROW(lua.script("x = non_overloaded(1, 2, 3)\nprint(x)"));
-
- /*
- // Cannot reasonably support: clang++ refuses to try enough
- // deductions to make this work
- lua.set_function("overloaded", overloaded);
- REQUIRE_NOTHROW(lua.script("print(overloaded(1))"));
-
- lua.set_function("overloaded", overloaded);
- REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2))"));
-
- lua.set_function("overloaded", overloaded);
- REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2, 3))"));
- */
- lua.set_function("overloaded", overloaded);
- REQUIRE_NOTHROW(lua.script("print(overloaded(1))"));
-
- lua.set_function("overloaded", overloaded);
- REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2))"));
-
- lua.set_function("overloaded", overloaded);
- REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2, 3))"));
-}
-
-TEST_CASE("functions/return-order-and-multi-get", "Check if return order is in the same reading order specified in Lua") {
- const static std::tuple triple = std::make_tuple(10, 11, 12);
- const static std::tuple paired = std::make_tuple(10, 10.f);
- sol::state lua;
- lua.set_function("f", [] {
- return std::make_tuple(10, 11, 12);
- } );
- int a = 0;
- lua.set_function( "h", []() {
- return std::make_tuple( 10, 10.0f );
- } );
- lua.script("function g() return 10, 11, 12 end\nx,y,z = g()");
- auto tcpp = lua.get("f").call();
- auto tlua = lua.get( "g" ).call();
- auto tcpp2 = lua.get( "h" ).call();
- auto tluaget = lua.get( "x", "y", "z" );
- REQUIRE(tcpp == triple);
- REQUIRE(tlua == triple);
- REQUIRE(tluaget == triple);
- REQUIRE(tcpp2 == paired);
-}
-
-TEST_CASE("functions/deducing-return-order-and-multi-get", "Check if return order is in the same reading order specified in Lua, with regular deducing calls") {
- const static std::tuple triple = std::make_tuple(10, 11, 12);
- sol::state lua;
- lua.set_function( "f_string", []() { return "this is a string!"; } );
- sol::function f_string = lua[ "f_string" ];
-
- // Make sure there are no overload collisions / compiler errors for automatic string conversions
- std::string f_string_result = f_string();
- REQUIRE(f_string_result == "this is a string!");
- f_string_result = f_string();
- REQUIRE(f_string_result == "this is a string!");
-
- lua.set_function("f", [] {
- return std::make_tuple(10, 11, 12);
- });
- lua.script("function g() return 10, 11, 12 end\nx,y,z = g()");
- std::tuple tcpp = lua.get("f")();
- std::tuple tlua = lua.get("g")();
- std::tuple tluaget = lua.get("x", "y", "z");
- 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 xyz: " << lua.get("x") << ',' << lua.get("y") << ',' << lua.get("z") << std::endl;
- REQUIRE(tcpp == triple);
- REQUIRE(tlua == triple);
- REQUIRE(tluaget == triple);
-}
-
-TEST_CASE("functions/sol::function-to-std::function", "check if conversion to std::function works properly and calls with correct arguments") {
- sol::state lua;
- lua.open_libraries(sol::lib::base);
-
- lua.set_function("testFunc", test_free_func);
- lua.set_function("testFunc2", test_free_func2);
- lua.script(
- "testFunc(function() print(\"hello std::function\") end)"
- );
- lua.script(
- "function m(a)\n"
- " print(\"hello std::function with arg \", a)\n"
- " return a\n"
- "end\n"
- "\n"
- "testFunc2(m, 1)"
- );
-}
-
-TEST_CASE("functions/returning-functions-from-C++-and-gettin-in-lua", "check to see if returning a functor and getting a functor from lua is possible") {
- sol::state lua;
- lua.open_libraries(sol::lib::base);
-
- lua.set_function("makefn", makefn);
- lua.set_function("takefn", takefn);
- lua.script("afx = makefn()\n"
- "print(afx())\n"
- "takefn(afx)\n");
-}
-
TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works properly") {
sol::state lua;
lua.open_libraries(sol::lib::base);
@@ -1219,7 +1069,7 @@ TEST_CASE("regressions/one", "issue number 48") {
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 on the type...") {
+TEST_CASE("usertype/get-set-references", "properly get and set with std::ref semantics. Note that to get, we must not use Unqualified on the type...") {
sol::state lua;
lua.new_usertype("vars",
@@ -1262,147 +1112,6 @@ TEST_CASE("interop/null-to-nil-and-back", "nil should be the given type when a p
"assert(x == nil)"));
}
-TEST_CASE( "functions/function_result-protected_function_result", "Function result should be the beefy return type for sol::function that allows for error checking and error handlers" ) {
- sol::state lua;
- lua.open_libraries( sol::lib::base, sol::lib::debug );
- static const char unhandlederrormessage[] = "true error message";
- static const char handlederrormessage[] = "doodle";
-
- // Some function; just using a lambda to be cheap
- auto doomfx = []() {
- std::cout << "doomfx called" << std::endl;
- throw std::runtime_error( unhandlederrormessage );
- };
- auto luadoomfx = [&lua]() {
- std::cout << "luadoomfx called" << std::endl;
- // Does not bypass error function, will call it
- luaL_error( lua.lua_state(), unhandlederrormessage );
- };
- lua.set_function("doom", doomfx);
- lua.set_function("luadoom", luadoomfx);
-
- auto cpphandlerfx = []( std::string x ) {
- std::cout << "c++ handler called with: " << x << std::endl;
- return handlederrormessage;
- };
- lua.set_function( "cpphandler", cpphandlerfx );
- lua.script(
- std::string( "function luahandler ( message )" )
- + " print('lua handler called with: ' .. message)"
- + " return '" + handlederrormessage + "'"
- + "end"
- );
- auto nontrampolinefx = [](lua_State*) -> int { throw "x";};
- lua_CFunction c_nontrampolinefx = nontrampolinefx;
- lua.set("nontrampoline", c_nontrampolinefx);
-
- sol::protected_function doom = lua[ "doom" ];
- sol::protected_function luadoom = lua["luadoom"];
- sol::protected_function nontrampoline = lua["nontrampoline"];
- sol::function luahandler = lua["luahandler"];
- sol::function cpphandler = lua[ "cpphandler" ];
- doom.error_handler = luahandler;
- luadoom.error_handler = cpphandler;
- nontrampoline.error_handler = cpphandler;
-
- {
- sol::protected_function_result result = doom();
- REQUIRE(!result.valid());
- std::string errorstring = result;
- REQUIRE(errorstring == handlederrormessage);
- }
- {
- sol::protected_function_result result = luadoom();
- REQUIRE(!result.valid());
- std::string errorstring = result;
- REQUIRE(errorstring == handlederrormessage);
- }
- {
- sol::protected_function_result result = nontrampoline();
- REQUIRE(!result.valid());
- std::string errorstring = result;
- REQUIRE(errorstring == handlederrormessage);
- }
-}
-
-TEST_CASE("functions/destructor-tests", "Show that proper copies / destruction happens") {
- static int created = 0;
- static int destroyed = 0;
- static void* last_call = nullptr;
- static void* static_call = reinterpret_cast(0x01);
- typedef void(* fptr)();
- struct x {
- x() {++created;}
- x(const x&) {++created;}
- x(x&&) {++created;}
- x& operator=(const x&) {return *this;}
- x& operator=(x&&) {return *this;}
- void func() {last_call = static_cast(this);};
- ~x () {++destroyed;}
- };
- struct y {
- y() {++created;}
- y(const x&) {++created;}
- y(x&&) {++created;}
- y& operator=(const x&) {return *this;}
- y& operator=(x&&) {return *this;}
- static void func() {last_call = static_call;};
- void operator()() {func();}
- operator fptr () { return func; }
- ~y () {++destroyed;}
- };
-
- // stateful functors/member functions should always copy unless specified
- {
- created = 0;
- destroyed = 0;
- last_call = nullptr;
- {
- sol::state lua;
- x x1;
- lua.set_function("x1copy", &x::func, x1);
- lua.script("x1copy()");
- REQUIRE(created == 2);
- REQUIRE(destroyed == 0);
- REQUIRE_FALSE(last_call == &x1);
-
- lua.set_function("x1ref", &x::func, std::ref(x1));
- lua.script("x1ref()");
- REQUIRE(created == 2);
- REQUIRE(destroyed == 0);
- REQUIRE(last_call == &x1);
- }
- REQUIRE(created == 2);
- REQUIRE(destroyed == 2);
- }
-
- // things convertible to a static function should _never_ be forced to make copies
- // therefore, pass through untouched
- {
- created = 0;
- destroyed = 0;
- last_call = nullptr;
- {
- sol::state lua;
- y y1;
- lua.set_function("y1copy", y1);
- lua.script("y1copy()");
- REQUIRE(created == 1);
- REQUIRE(destroyed == 0);
- REQUIRE(last_call == static_call);
-
- last_call = nullptr;
- lua.set_function("y1ref", std::ref(y1));
- lua.script("y1ref()");
- REQUIRE(created == 1);
- REQUIRE(destroyed == 0);
- REQUIRE(last_call == static_call);
- }
- REQUIRE(created == 1);
- REQUIRE(destroyed == 1);
- }
-}
-
TEST_CASE("usertype/destructor-tests", "Show that proper copies / destruction happens") {
static int created = 0;
static int destroyed = 0;