Improved functions example and adjusted all errors for g++ conformance with -Wall -Werror

This commit is contained in:
ThePhD 2016-02-10 12:12:09 -05:00
parent 2788abb34e
commit 427194bc92
9 changed files with 77 additions and 61 deletions

View File

@ -15,55 +15,76 @@ struct multiplier {
} }
}; };
int main() { inline std::string make_string( std::string input ) {
sol::state lua; return "string: " + input;
lua.open_libraries(sol::lib::base); }
// setting a function is simple int main() {
lua.set_function("my_add", my_add); sol::state lua;
lua.open_libraries(sol::lib::base);
// you could even use a lambda
lua.set_function("my_mul", [](double x, double y) { return x * y; }); // setting a function is simple
lua.set_function("my_add", my_add);
// member function pointers and functors as well
lua.set_function("mult_by_ten", multiplier{}); // you could even use a lambda
lua.set_function("mult_by_five", &multiplier::by_five); lua.set_function("my_mul", [](double x, double y) { return x * y; });
// assert that the functions work // member function pointers and functors as well
lua.script("assert(my_add(10, 11) == 21)"); lua.set_function("mult_by_ten", multiplier{});
lua.script("assert(my_mul(4.5, 10) == 45)"); lua.set_function("mult_by_five", &multiplier::by_five);
lua.script("assert(mult_by_ten(50) == 500)");
lua.script("assert(mult_by_five(10) == 50)"); // assert that the functions work
lua.script("assert(my_add(10, 11) == 21)");
// using lambdas, functions could have state. lua.script("assert(my_mul(4.5, 10) == 45)");
int x = 0; lua.script("assert(mult_by_ten(50) == 500)");
lua.set_function("inc", [&x]() { x += 10; }); lua.script("assert(mult_by_five(10) == 50)");
// calling a stateful lambda modifies the value // using lambdas, functions could have state.
lua.script("inc()"); int x = 0;
assert(x == 10); lua.set_function("inc", [&x]() { x += 10; });
// this can be done as many times as you want // calling a stateful lambda modifies the value
lua.script("inc()\ninc()\ninc()"); lua.script("inc()");
assert(x == 40); assert(x == 10);
// retrieval of a function is done similarly // this can be done as many times as you want
// to other variables, using sol::function lua.script("inc()\ninc()\ninc()");
sol::function add = lua["my_add"]; assert(x == 40);
assert(add.call<int>(10, 11) == 21);
// retrieval of a function is done similarly
// multi-return functions are supported using // to other variables, using sol::function
// std::tuple as the interface. sol::function add = lua["my_add"];
lua.set_function("multi", []{ return std::make_tuple(10, "goodbye"); }); int value = add(10, 11);
lua.script("x, y = multi()"); assert(add.call<int>(10, 11) == 21);
lua.script("assert(x == 10 and y == 'goodbye')"); assert(value == 21);
auto multi = lua.get<sol::function>("multi"); // multi-return functions are supported using
int first; // std::tuple as the interface.
std::string second; lua.set_function("multi", [] { return std::make_tuple(10, "goodbye"); });
std::tie(first, second) = multi.call<int, std::string>(); lua.script("x, y = multi()");
lua.script("assert(x == 10 and y == 'goodbye')");
// assert the values
assert(first == 10); auto multi = lua.get<sol::function>("multi");
assert(second == "goodbye"); int first;
std::string second;
std::tie(first, second) = multi.call<int, std::string>();
// use the values
assert(first == 10);
assert(second == "goodbye");
// you can even overload functions
// just pass in the different functions
// you want to pack into a single name:
// make SURE they take different number of
// arguments/different types!
lua.set_function("func", sol::overload([](int x) { return x; }, make_string, my_add));
// All these functions are now overloaded through "func"
lua.script(R"(
print(func(1))
print(func("bark"))
print(func(1,2))
)");
} }

View File

@ -386,14 +386,13 @@ struct pusher<overload_set<Functions...>> {
template<typename Signature> template<typename Signature>
struct getter<std::function<Signature>> { struct getter<std::function<Signature>> {
typedef function_traits<Signature> fx_t; typedef function_traits<Signature> fx_t;
typedef typename fx_t::args_type args_t; typedef typename fx_t::args_type args_type;
typedef typename tuple_types_t<typename fx_t::return_type> ret_t; typedef tuple_types_t<typename fx_t::return_type> return_type;
template<typename... FxArgs, typename... Ret> template<typename... FxArgs, typename... Ret>
static std::function<Signature> get_std_func(types<FxArgs...>, types<Ret...>, lua_State* L, int index = -1) { static std::function<Signature> get_std_func(types<FxArgs...>, types<Ret...>, lua_State* L, int index = -1) {
typedef typename function_traits<Signature>::return_type return_t;
sol::function f(L, index); sol::function f(L, index);
auto fx = [f, L, index](FxArgs&&... args) -> return_t { auto fx = [f, L, index](FxArgs&&... args) -> return_type_t<Ret...> {
return f(types<Ret...>(), std::forward<FxArgs>(args)...); return f(types<Ret...>(), std::forward<FxArgs>(args)...);
}; };
return std::move(fx); return std::move(fx);
@ -414,7 +413,7 @@ struct getter<std::function<Signature>> {
} }
static std::function<Signature> get(lua_State* L, int index) { static std::function<Signature> get(lua_State* L, int index) {
return get_std_func(args_t(), ret_t(), L, index); return get_std_func(args_type(), return_type(), L, index);
} }
}; };
} // stack } // stack

View File

@ -89,11 +89,6 @@ public:
return get(tr, tr); return get(tr, tr);
} }
template <typename K>
decltype(auto) operator[](K&& key) const {
return get<table>()[std::forward<K>(key)];
}
~function_result() { ~function_result() {
stack::remove(L, index, popcount); stack::remove(L, index, popcount);
} }

View File

@ -49,7 +49,7 @@ function_packer<Sig, Args...> function_pack( Args&&... args ) {
return function_packer<Sig, Args...>(std::forward<Args>(args)...); return function_packer<Sig, Args...>(std::forward<Args>(args)...);
} }
inline bool check_types(types<>, indices<>, lua_State* L, int) { inline bool check_types(types<>, indices<>, lua_State*, int) {
return true; return true;
} }

View File

@ -37,7 +37,7 @@ struct overloaded_function : base_function {
} }
int match_arity(lua_State* L, std::ptrdiff_t x, indices<>) { int match_arity(lua_State*, std::ptrdiff_t, indices<>) {
throw error("no matching function call takes this number of arguments"); throw error("no matching function call takes this number of arguments");
} }
@ -99,7 +99,7 @@ struct usertype_overloaded_function : base_function {
} }
int match_arity(lua_State* L, std::ptrdiff_t x, indices<>) { int match_arity(lua_State*, std::ptrdiff_t, indices<>) {
throw error("no matching function call takes this number of arguments"); throw error("no matching function call takes this number of arguments");
} }
@ -154,7 +154,7 @@ struct usertype_indexing_function<overload_set<Functions...>, T> : base_function
usertype_indexing_function(std::string name, Functions... fxs) usertype_indexing_function(std::string name, Functions... fxs)
: overloads({function_traits<Functions>::arity, fxs}...), name(std::move(name)) {} : overloads({function_traits<Functions>::arity, fxs}...), name(std::move(name)) {}
int match_arity(lua_State* L, std::ptrdiff_t x, indices<>) { int match_arity(lua_State*, std::ptrdiff_t, indices<>) {
throw error("no matching function call takes this number of arguments"); throw error("no matching function call takes this number of arguments");
} }

View File

@ -75,7 +75,7 @@ struct static_member_function {
template<typename... Ret, typename... Args> template<typename... Ret, typename... Args>
static int typed_call(types<Ret...> tr, types<Args...> ta, T& item, function_type& ifx, lua_State* L) { static int typed_call(types<Ret...> tr, types<Args...> ta, T& item, function_type& ifx, lua_State* L) {
auto fx = [&item, &ifx](Args&&... args) -> return_type { return (item.*ifx)(std::forward<Args>(args)...); }; auto fx = [&item, &ifx](Args&&... args) -> return_type_t<Ret...> { return (item.*ifx)(std::forward<Args>(args)...); };
decltype(auto) r = stack::call(L, 0, tr, ta, fx); decltype(auto) r = stack::call(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);

View File

@ -40,7 +40,7 @@ struct push_pop<true, T> {
template <bool top_level = false, typename T> template <bool top_level = false, typename T>
push_pop<top_level, T> push_popper(T&& x) { push_pop<top_level, T> push_popper(T&& x) {
return push_pop<top_level, T>(std::forward<T>(x)); return push_pop<top_level, T>(std::forward<T>(x));
}; }
} // stack } // stack
class reference { class reference {

View File

@ -252,7 +252,8 @@ private:
template<typename Fx> template<typename Fx>
std::unique_ptr<base_function> make_function(const std::string&, Fx&& func) { std::unique_ptr<base_function> make_function(const std::string&, Fx&& func) {
typedef Unqualified<Fx> Fxu; typedef Unqualified<Fx> Fxu;
typedef Unqualified<std::remove_pointer_t<function_traits<Fxu>::arg<0>>> Argu; typedef std::tuple_element_t<0, typename function_traits<Fxu>::args_tuple_type> Arg0;
typedef Unqualified<std::remove_pointer_t<Arg0>> Argu;
static_assert(std::is_base_of<Argu, T>::value, "Any non-member-function must have a first argument which is covariant with the desired usertype."); static_assert(std::is_base_of<Argu, T>::value, "Any non-member-function must have a first argument which is covariant with the desired usertype.");
typedef std::decay_t<Fxu> function_type; typedef std::decay_t<Fxu> function_type;
return std::make_unique<usertype_function<function_type, T>>(func); return std::make_unique<usertype_function<function_type, T>>(func);

View File

@ -85,7 +85,7 @@ struct self_test {
} }
}; };
int func_1(int a) { int func_1(int) {
return 1; return 1;
} }
@ -93,11 +93,11 @@ std::string func_1s(std::string a) {
return "string: " + a; return "string: " + a;
} }
int func_2(int a, int b) { int func_2(int, int) {
return 2; return 2;
} }
void func_3(int a, int b, int c) { void func_3(int, int, int) {
} }
@ -1006,7 +1006,7 @@ TEST_CASE("references/get-set", "properly get and set with std::ref semantics. N
REQUIRE(var.boop != my_var.boop); REQUIRE(var.boop != my_var.boop);
REQUIRE(std::addressof(ref_var) == std::addressof(rvar)); REQUIRE(std::addressof(ref_var) == std::addressof(rvar));
//REQUIRE(std::addressof(proxy_ref_var.get()) == std::addressof(rvar)); REQUIRE(std::addressof(proxy_ref_var.get()) == std::addressof(rvar));
REQUIRE(rvar.boop == 5); REQUIRE(rvar.boop == 5);
REQUIRE(rvar.boop == ref_var.boop); REQUIRE(rvar.boop == ref_var.boop);
} }
@ -1042,7 +1042,7 @@ TEST_CASE( "functions/function_result-protected_function", "Function result shou
// Does not bypass error function, will call it // Does not bypass error function, will call it
luaL_error( lua.lua_state(), "BIG ERROR MESSAGES!" ); luaL_error( lua.lua_state(), "BIG ERROR MESSAGES!" );
}; };
auto specialhandler = []( std::string message ) { auto specialhandler = []( std::string ) {
return errormessage2; return errormessage2;
}; };