Several changes. I took away operator() for the proxy type, because it'd interfere with the Callable type and all. Alas, good things do die I suppose. =[

But! I left it on the `sol::function` type, because it's necessary to discard returns. The .call is still there, though, just incase you need it. <3
reverse_indices_builder is also there, to make sure we can push and pop without the lua api taking our types and breaking them for the std::tuple returns.
All is at it should be~
This commit is contained in:
ThePhD 2013-12-14 23:25:44 -05:00
parent 913611c042
commit ed0b83f8b0
6 changed files with 44 additions and 29 deletions

View File

@ -68,7 +68,7 @@ public:
template<typename... Ret, typename... Args>
typename multi_return<Ret...>::type operator()(types<Ret...>, Args&&... args) {
return call<Ret...>(std::forward<Args>(args)...);
return call<Ret...>(std::forward<Args>(args)...);
}
template<typename... Ret, typename... Args>

View File

@ -207,7 +207,7 @@ inline int push_user(lua_State* L, T& item) {
namespace detail {
template<typename T, std::size_t... I>
inline void push(lua_State* L, indices<I...>, const T& tuplen) {
inline void push_tuple(lua_State* L, indices<I...>, T&& tuplen) {
using swallow = char[ 1 + sizeof...(I) ];
swallow {'\0', (sol::stack::push(L, std::get<I>(tuplen)), '\0')... };
}
@ -228,7 +228,12 @@ auto ltr_pop(lua_State* L, F&& f, types<Head, Tail...>, Vs&&... vs) -> decltype(
template<typename... Args>
inline void push(lua_State* L, const std::tuple<Args...>& tuplen) {
detail::push(L, build_indices<sizeof...(Args)>(), tuplen);
detail::push_tuple(L, build_reverse_indices<sizeof...(Args)>(), tuplen);
}
template<typename... Args>
inline void push(lua_State* L, std::tuple<Args...>&& tuplen) {
detail::push_tuple(L, build_reverse_indices<sizeof...(Args)>(), std::move(tuplen));
}
template<typename... Args, typename TFx>

View File

@ -119,16 +119,6 @@ private:
return t.get<U>(key);
}
template<typename... Args>
void operator()( Args&&... args ) {
call<>( std::forward<Args>( args )... );
}
template<typename... Ret, typename... Args>
typename multi_return<Ret...>::type operator()(types<Ret...>, Args&&... args) {
return call<Ret...>(std::forward<Args>(args)...);
}
template<typename... Ret, typename... Args>
typename multi_return<Ret...>::type call(Args&&... args) {
return t.get<function>(key)(types<Ret...>(), std::forward<Args>(args)...);

View File

@ -63,17 +63,17 @@ struct is_function_impl<T, true> {
};
} // detail
template <typename... Args>
template<typename... Args>
struct multi_return {
typedef std::tuple<Args...> type;
};
template <typename T>
template<typename T>
struct multi_return<T> {
typedef T type;
};
template <>
template<>
struct multi_return<> : types<>{
typedef void type;
};

View File

@ -26,8 +26,23 @@
#include <cstddef>
namespace sol {
template<typename... Ts>
struct reverse_tuple;
template<>
struct reverse_tuple<std::tuple<>> {
using type = std::tuple<>;
};
template<typename T, typename... Ts>
struct reverse_tuple<std::tuple<T, Ts...>> {
using head = std::tuple<T>;
using tail = typename reverse_tuple<std::tuple<Ts...>>::type;
using type = decltype(std::tuple_cat(std::declval<tail>(), std::declval<head>()));
};
template<size_t... Ns>
struct indices {};
struct indices { typedef indices type; };
template<size_t N, size_t... Ns>
struct build_indices : build_indices<N - 1, N - 1, Ns...> {};
@ -35,6 +50,12 @@ struct build_indices : build_indices<N - 1, N - 1, Ns...> {};
template<size_t... Ns>
struct build_indices<0, Ns...> : indices<Ns...> {};
template<size_t N, size_t... Ns>
struct build_reverse_indices : build_reverse_indices<N - 1, Ns..., N - 1> {};
template<size_t... Ns>
struct build_reverse_indices<0, Ns...> : indices<Ns...> {};
template<typename... Args>
struct types : build_indices<sizeof...(Args)> {};

View File

@ -117,34 +117,33 @@ TEST_CASE("advanced/callLambdaReturns", "Checks for lambdas returning values") {
sol::state lua;
REQUIRE_NOTHROW(lua.set_function("a", [ ] { return 42; }));
REQUIRE(lua["a"]( sol::types<int>() ) == 42);
REQUIRE(lua["a"].call<int>() == 42);
REQUIRE_NOTHROW(lua.set_function("b", [ ] { return 42u; }));
REQUIRE(lua["b"](sol::types<unsigned int>()) == 42u);
REQUIRE(lua["b"].call<unsigned int>() == 42u);
REQUIRE_NOTHROW(lua.set_function("c", [ ] { return 3.14; }));
REQUIRE(lua["c"](sol::types<double>()) == 3.14);
REQUIRE(lua["c"].call<double>() == 3.14);
REQUIRE_NOTHROW(lua.set_function("d", [ ] { return 6.28f; }));
REQUIRE(lua["d"](sol::types<float>()) == 6.28f);
REQUIRE(lua["d"].call<float>() == 6.28f);
REQUIRE_NOTHROW(lua.set_function("e", [ ] { return "lol"; }));
REQUIRE(lua["e"](sol::types<std::string>()) == lol);
REQUIRE(lua["e"].call<std::string>() == lol);
REQUIRE_NOTHROW(lua.set_function("f", [ ] { return true; }));
REQUIRE(lua["f"](sol::types<bool>()));
REQUIRE(lua["f"].call<bool>());
REQUIRE_NOTHROW(lua.set_function("g", [ ] { return std::string("str"); }));
REQUIRE(lua["g"](sol::types<std::string>()) == str);
REQUIRE(lua["g"].call<std::string>() == str);
REQUIRE_NOTHROW(lua.set_function("h", [ ] { }));
REQUIRE_NOTHROW(lua["h"](sol::types<>()));
REQUIRE_NOTHROW(lua["h"].call());
REQUIRE_NOTHROW(lua.set_function("i", [ ] { return sol::nil; }));
REQUIRE(lua["i"](sol::types<sol::nil_t>()) == sol::nil);
REQUIRE_NOTHROW(lua.set_function("j", [ ] { return std::make_tuple(1, 6.28f, 3.14, std::string( "heh" )); } ));
REQUIRE(lua["j"](sol::types<int, float, double, std::string>()) == heh_tuple);
REQUIRE(lua["i"].call<sol::nil_t>() == sol::nil);
REQUIRE_NOTHROW(lua.set_function("j", [ ] { return std::make_tuple(1, 6.28f, 3.14, std::string("heh")); }));
REQUIRE((lua["j"].call<int, float, double, std::string>() == heh_tuple));
}
TEST_CASE("advanced/callLambda2", "A C++ lambda is exposed to lua and called") {