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;
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);
}
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)...);
return r;
}
@ -61,11 +61,20 @@ public:
function_result& operator=(function_result&&) = default;
template<typename T>
operator T () const {
auto tr = tuple_types<T>();
T get() const {
tuple_types<Unqualified<T>> 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() {
lua_pop(L, returncount);
}
@ -122,12 +131,14 @@ public:
}
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)...);
}
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();
int pushcount = stack::push_args(state(), std::forward<Args>(args)...);
auto tr = types<Ret...>();

View File

@ -65,50 +65,24 @@ public:
tbl.set(key, std::forward<U>(other));
}
operator nil_t() const {
return get<nil_t>();
operator const char* () const {
return get<const char*>();
}
operator object() const {
return get<object>();
}
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 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>();
}
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)...);
}
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>

View File

@ -141,6 +141,12 @@ bool check(lua_State* L, int index) {
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 {
const bool default_check_arguments =
#ifdef SOL_CHECK_ARGUMENTS
@ -258,7 +264,7 @@ struct getter<T*> {
type t = type_of(L, index);
if (t == type::nil)
return nullptr;
return getter<T&>{}.get(L, index);
return std::addressof(getter<T&>{}.get(L, index));
}
};

View File

@ -30,24 +30,23 @@
namespace sol {
class table : public reference {
friend class state;
template<typename T, typename U>
auto single_get(U&& key) const -> decltype(stack::get<T>(nullptr, 0)) {
template<typename T, typename Key>
stack::get_return<T> single_get(Key&& key) const {
push();
stack::push(state(), std::forward<U>(key));
stack::push(state(), std::forward<Key>(key));
lua_gettable(state(), -2);
type_assert(state(), -1, type_of<T>());
auto&& result = stack::pop<T>(state());
lua_pop(state(), 1);
stack::get_return<T> result = stack::pop<T>(state());
pop();
return result;
}
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))...)) {
return std::make_tuple(single_get<Ret>(std::get<I>(keys))...);
stack::get_return<Ret...> tuple_get(types<Ret...>, indices<I...>, Keys&& keys) const {
return stack::get_return<Ret...>(single_get<Ret>(std::get<I>(keys))...);
}
template<typename Keys, std::size_t I, typename Ret>
auto tuple_get(types<Ret>, indices<I>, Keys&& keys) const -> decltype(single_get<Ret>(std::get<I>(keys))) {
template<typename Keys, typename Ret, std::size_t I>
stack::get_return<Ret> tuple_get(types<Ret>, indices<I>, Keys&& keys) const {
return single_get<Ret>(std::get<I>(keys));
}
@ -58,9 +57,8 @@ public:
}
template<typename... Ret, typename... Keys>
auto get(Keys&&... keys) const -> decltype(tuple_get(types<Ret...>(), types<Ret...>(), std::tie(std::forward<Keys>(keys)...))) {
types<Ret...> tr;
return tuple_get(tr, tr, std::tie(std::forward<Keys>(keys)...));
stack::get_return<Ret...> get( Keys&&... keys ) const {
return tuple_get(types<Ret...>(), build_indices<sizeof...(Ret)>(), std::tie(keys...));
}
template<typename T, typename U>

View File

@ -122,8 +122,11 @@ struct return_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>
using ReturnType = typename return_type<Tn...>::type;
using ReturnType = ReturnTypeOr<void, Tn...>;
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);
}
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") {
sol::state lua;
lua.open_libraries(sol::lib::base);