tests for the new decaying functionality

need to test with clang++/g++ to see if it still works
This commit is contained in:
ThePhD 2015-07-22 02:54:43 -04:00
parent d4fe51725c
commit dbeb8b5fcb
6 changed files with 89 additions and 70 deletions

View File

@ -40,12 +40,12 @@ private:
int returncount; int returncount;
template <typename T, std::size_t I> template <typename T, std::size_t I>
T get(types<T>, indices<I>) const { stack::get_return<T> get(types<T>, indices<I>) const {
return stack::get<T>(L, index); return stack::get<T>(L, index);
} }
template <typename... Ret, std::size_t... I> template <typename... Ret, std::size_t... I>
std::tuple<Ret...> get(types<Ret...>, indices<I...>) const { stack::get_return<Ret...> get(types<Ret...>, indices<I...>) const {
auto r = std::make_tuple(stack::get<Ret>(L, index + I)...); auto r = std::make_tuple(stack::get<Ret>(L, index + I)...);
return r; return r;
} }
@ -60,12 +60,21 @@ public:
function_result(function_result&&) = default; function_result(function_result&&) = default;
function_result& operator=(function_result&&) = default; function_result& operator=(function_result&&) = default;
template <typename T> template<typename T>
operator T () const { T get() const {
auto tr = tuple_types<T>(); tuple_types<Unqualified<T>> tr;
return get(tr, tr); return get(tr, tr);
} }
operator const char* () const {
return get<const char*>();
}
template<typename T, EnableIf<Not<std::is_same<Unqualified<T>, const char*>>, Not<std::is_same<Unqualified<T>, char>>, Not<std::is_same<Unqualified<T>, std::string>>, Not<std::is_same<Unqualified<T>, std::initializer_list<char>>>> = 0>
operator T () const {
return get<T>();
}
~function_result() { ~function_result() {
lua_pop(L, returncount); lua_pop(L, returncount);
} }
@ -122,12 +131,14 @@ public:
} }
template<typename... Ret, typename... Args> template<typename... Ret, typename... Args>
ReturnType<Ret...> operator()(types<Ret...>, Args&&... args) const { auto operator()(types<Ret...>, Args&&... args) const
-> decltype(call<Ret...>(std::forward<Args>(args)...)) {
return call<Ret...>(std::forward<Args>(args)...); return call<Ret...>(std::forward<Args>(args)...);
} }
template<typename... Ret, typename... Args> template<typename... Ret, typename... Args>
auto call(Args&&... args) const -> decltype(invoke(types<Ret...>(), types<Ret...>(), 0)) { auto call(Args&&... args) const
-> decltype(invoke(types<Ret...>(), types<Ret...>(), 0)) {
push(); push();
int pushcount = stack::push_args(state(), std::forward<Args>(args)...); int pushcount = stack::push_args(state(), std::forward<Args>(args)...);
auto tr = types<Ret...>(); auto tr = types<Ret...>();

View File

@ -52,7 +52,7 @@ public:
template<typename... Args> template<typename... Args>
proxy& set_function(Args&&... args) { proxy& set_function(Args&&... args) {
tbl.set_function(key, std::forward<Args>(args)...); tbl.set_function(key, std::forward<Args>(args)...);
return *this; return *this;
} }
template<typename U, EnableIf<Function<Unqualified<U>>> = 0> template<typename U, EnableIf<Function<Unqualified<U>>> = 0>
@ -65,50 +65,24 @@ public:
tbl.set(key, std::forward<U>(other)); tbl.set(key, std::forward<U>(other));
} }
operator nil_t() const { operator const char* () const {
return get<nil_t>(); return get<const char*>();
} }
operator object() const { template<typename T, EnableIf<Not<std::is_same<Unqualified<T>, const char*>>, Not<std::is_same<Unqualified<T>, char>>, Not<std::is_same<Unqualified<T>, std::string>>, Not<std::is_same<Unqualified<T>, std::initializer_list<char>>>> = 0>
return get<object>(); operator T () const {
} return get<T>();
operator function() const {
return get<function>();
}
operator Unqualified<Table>() const {
return get<Unqualified<Table>>();
}
operator std::string() const {
return get<std::string>();
}
template<typename T = void>
operator bool() const {
return get<bool>();
}
template<typename T = void>
operator double() const {
return get<double>();
}
template<typename T = void>
operator float() const {
return get<float>();
}
template<typename T = void>
operator int() const {
return get<int>();
} }
template<typename... Ret, typename... Args> template<typename... Ret, typename... Args>
typename return_type<Ret...>::type call(Args&&... args) { stack::get_return_or<function_result, Ret...> call(Args&&... args) {
return tbl.template get<function>(key)(types<Ret...>(), std::forward<Args>(args)...); return tbl.template get<function>(key)(types<Ret...>(), std::forward<Args>(args)...);
} }
template<typename... Args>
function_result operator()(Args&&... args) {
return tbl.template get<function>(key)(std::forward<Args>(args)...);
}
}; };
template<typename Table, typename Key, typename T> template<typename Table, typename Key, typename T>

View File

@ -141,6 +141,12 @@ bool check(lua_State* L, int index) {
return check<T>(L, index, handler); return check<T>(L, index, handler);
} }
template<typename... Ret>
using get_return = ReturnType<decltype(stack::get<Ret>( nullptr, 0 ))...>;
template<typename Empty, typename... Ret>
using get_return_or = ReturnTypeOr<Empty, decltype(stack::get<Ret>( nullptr, 0 ))...>;
namespace detail { namespace detail {
const bool default_check_arguments = const bool default_check_arguments =
#ifdef SOL_CHECK_ARGUMENTS #ifdef SOL_CHECK_ARGUMENTS
@ -258,7 +264,7 @@ struct getter<T*> {
type t = type_of(L, index); type t = type_of(L, index);
if (t == type::nil) if (t == type::nil)
return nullptr; return nullptr;
return getter<T&>{}.get(L, index); return std::addressof(getter<T&>{}.get(L, index));
} }
}; };

View File

@ -30,24 +30,23 @@
namespace sol { namespace sol {
class table : public reference { class table : public reference {
friend class state; friend class state;
template<typename T, typename U> template<typename T, typename Key>
auto single_get(U&& key) const -> decltype(stack::get<T>(nullptr, 0)) { stack::get_return<T> single_get(Key&& key) const {
push(); push();
stack::push(state(), std::forward<U>(key)); stack::push(state(), std::forward<Key>(key));
lua_gettable(state(), -2); lua_gettable(state(), -2);
type_assert(state(), -1, type_of<T>()); stack::get_return<T> result = stack::pop<T>(state());
auto&& result = stack::pop<T>(state()); pop();
lua_pop(state(), 1);
return result; return result;
} }
template<typename Keys, typename... Ret, std::size_t... I> template<typename Keys, typename... Ret, std::size_t... I>
auto tuple_get(types<Ret...>, indices<I...>, Keys&& keys) const -> decltype(std::make_tuple(single_get<Ret>(std::get<I>(keys))...)) { stack::get_return<Ret...> tuple_get(types<Ret...>, indices<I...>, Keys&& keys) const {
return std::make_tuple(single_get<Ret>(std::get<I>(keys))...); return stack::get_return<Ret...>(single_get<Ret>(std::get<I>(keys))...);
} }
template<typename Keys, std::size_t I, typename Ret> template<typename Keys, typename Ret, std::size_t I>
auto tuple_get(types<Ret>, indices<I>, Keys&& keys) const -> decltype(single_get<Ret>(std::get<I>(keys))) { stack::get_return<Ret> tuple_get(types<Ret>, indices<I>, Keys&& keys) const {
return single_get<Ret>(std::get<I>(keys)); return single_get<Ret>(std::get<I>(keys));
} }
@ -58,9 +57,8 @@ public:
} }
template<typename... Ret, typename... Keys> template<typename... Ret, typename... Keys>
auto get(Keys&&... keys) const -> decltype(tuple_get(types<Ret...>(), types<Ret...>(), std::tie(std::forward<Keys>(keys)...))) { stack::get_return<Ret...> get( Keys&&... keys ) const {
types<Ret...> tr; return tuple_get(types<Ret...>(), build_indices<sizeof...(Ret)>(), std::tie(keys...));
return tuple_get(tr, tr, std::tie(std::forward<Keys>(keys)...));
} }
template<typename T, typename U> template<typename T, typename U>
@ -119,13 +117,13 @@ public:
} }
template<typename T> template<typename T>
proxy<table, T> operator[](T&& key) { proxy<table, T> operator[]( T&& key ) {
return proxy<table, T>(*this, std::forward<T>(key)); return proxy<table, T>( *this, std::forward<T>( key ) );
} }
template<typename T> template<typename T>
proxy<const table, T> operator[](T&& key) const { proxy<const table, T> operator[]( T&& key ) const {
return proxy<const table, T>(*this, std::forward<T>(key)); return proxy<const table, T>( *this, std::forward<T>( key ) );
} }
void pop(int n = 1) const noexcept { void pop(int n = 1) const noexcept {

View File

@ -122,8 +122,11 @@ struct return_type<> {
typedef void type; typedef void type;
}; };
template <typename Empty, typename... Tn>
using ReturnTypeOr = typename std::conditional<(sizeof...(Tn) < 1), Empty, typename return_type<Tn...>::type>::type;
template <typename... Tn> template <typename... Tn>
using ReturnType = typename return_type<Tn...>::type; using ReturnType = ReturnTypeOr<void, Tn...>;
namespace detail { namespace detail {

View File

@ -488,6 +488,33 @@ TEST_CASE("functions/return_order_and_multi_get", "Check if return order is in t
REQUIRE(tluaget == triple); REQUIRE(tluaget == triple);
} }
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<int, int, int> 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<int, int, int> tcpp = lua.get<sol::function>("f")();
std::tuple<int, int, int> tlua = lua.get<sol::function>("g")();
std::tuple<int, int, int> 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 << "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;
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") { TEST_CASE("functions/sol::function to std::function", "check if conversion to std::function works properly and calls with correct arguments") {
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);