Hammer down function behavior and provide an example to show how it works

This commit is contained in:
ThePhD 2018-03-03 13:42:13 -05:00
parent 1e5c256394
commit cd13f2dc0d
5 changed files with 106 additions and 9 deletions

View File

@ -0,0 +1,53 @@
#define SOL_CHECK_ARGUMENTS 1
#include <sol.hpp>
#include "assert.hpp"
#include <iostream>
int main(int, char*[]) {
std::cout << "=== functions empty args ===" << std::endl;
// sol::reference, sol::Stack_reference,
// sol::object (and main_* types) can all be
// used to capture "nil", or "none" when a function
// leaves it off
auto my_defaulting_function = [](sol::object maybe_defaulted) -> int {
// if it's nil, it's "unused" or "inactive"
bool inactive = maybe_defaulted == sol::lua_nil;
if (inactive) {
return 0;
}
if (maybe_defaulted.is<int>()) {
int value = maybe_defaulted.as<int>();
return value;
}
return 1;
};
sol::state lua;
lua.open_libraries(sol::lib::base);
// copy function in (use std::ref to change this behavior)
lua.set_function("defaulting_function", my_defaulting_function);
sol::string_view code = R"(
result = defaulting_function(24)
result_nothing = defaulting_function()
result_nil = defaulting_function(nil)
result_string = defaulting_function('meow')
print('defaulting_function(24), returned:', result)
print('defaulting_function(), returned:', result_nothing)
print('defaulting_function(nil), returned:', result_nil)
print('defaulting_function(\'meow\'), returned:', result_string)
assert(result == 24)
assert(result_nothing == 0)
assert(result_nil == 0)
assert(result_string == 1)
)";
lua.safe_script(code);
std::cout << std::endl;
return 0;
}

View File

@ -7899,12 +7899,7 @@ namespace stack {
template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
tracking.use(1);
bool success = !lua_isnone(L, index);
if (!success) {
// expected type, actual type
handler(L, index, type::poly, type_of(L, index), "");
}
return success;
return true;
}
};

View File

@ -239,7 +239,7 @@ namespace stack {
template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
tracking.use(1);
bool success = !lua_isnone(L, index);
bool success = is_lua_reference<T>::value || !lua_isnone(L, index);
if (!success) {
// expected type, actual type
handler(L, index, type::poly, type_of(L, index), "");

View File

@ -135,15 +135,16 @@ namespace stack {
typedef std::integral_constant<bool, V_size::value == 0> V_is_empty;
template <typename Handler>
static optional<V> get_empty(std::true_type, lua_State* L, int index, Handler&& handler, record& tracking) {
static optional<V> get_empty(std::true_type, lua_State*, int, Handler&&, record&) {
return nullopt;
}
template <typename Handler>
static optional<V> get_empty(std::false_type, lua_State* L, int index, Handler&& handler, record& tracking) {
static optional<V> get_empty(std::false_type, lua_State* L, int index, Handler&& handler, record&) {
typedef std::variant_alternative_t<0, V> T;
// This should never be reached...
// please check your code and understand what you did to bring yourself here
// maybe file a bug report, or 5
handler(L, index, type::poly, type_of(L, index), "this variant code should never be reached: if it has, you have done something so terribly wrong");
return nullopt;
}

View File

@ -1490,6 +1490,54 @@ TEST_CASE("functions/unique_usertype overloading", "make sure overloading can wo
};
}
TEST_CASE("functions/lua style default arguments", "allow default arguments using sol::reference and sol::object") {
auto def_f1 = [](sol::object defaulted) -> int {
bool inactive = defaulted == sol::lua_nil; // inactive by default
if (inactive) {
return 20;
}
return 10;
};
auto def_f2 = [](sol::reference defaulted) -> int {
bool inactive = defaulted == sol::lua_nil; // inactive by default
if (inactive) {
return 20;
}
return 10;
};
auto def_f3 = [](sol::stack_reference defaulted) -> int {
bool inactive = defaulted == sol::lua_nil; // inactive by default
if (inactive) {
return 20;
}
return 10;
};
sol::state lua;
lua.set_function("f1", def_f1);
lua.set_function("f2", def_f2);
lua.set_function("f3", def_f3);
auto result = lua.safe_script(R"(
v1d, v1nd = f1(), f1(1)
v2d, v2nd = f2(), f2(1)
v3d, v3nd = f3(), f3(1)
)", sol::script_pass_on_error);
REQUIRE(result.valid());
int v1d = lua["v1d"];
int v1nd = lua["v1nd"];
int v2d = lua["v2d"];
int v2nd = lua["v2nd"];
int v3d = lua["v3d"];
int v3nd = lua["v3nd"];
REQUIRE(20 == v1d);
REQUIRE(20 == v2d);
REQUIRE(20 == v3d);
REQUIRE(10 == v1nd);
REQUIRE(10 == v2nd);
REQUIRE(10 == v3nd);
}
#if !defined(_MSC_VER) || !(defined(_WIN32) && !defined(_WIN64))
TEST_CASE("functions/noexcept", "allow noexcept functions to be serialized properly into Lua using sol2") {