From 8871d5cbb15a200906d975a08f1a808de930a820 Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Mon, 27 Jan 2014 15:24:48 -0800 Subject: [PATCH] Support return type inferencing for multi-return functions. --- README.md | 8 +++++--- include/Selector.h | 9 +++++++++ include/Tuple.h | 22 ++++++++++++++++++++++ test/interop_tests.h | 6 +++--- 4 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 include/Tuple.h diff --git a/README.md b/README.md index cfecbca..dd899ca 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ assert(result == 7); // Call function that returns multiple values int sum, difference; -std::tie(sum, difference) = state["sum_and_difference"].Call(3, 1); +sel::tie(sum, difference) = state["sum_and_difference"](3, 1); assert(sum == 4 && difference == 2); // Call function in table @@ -142,8 +142,10 @@ Note that `Call`, unlike return. This is because the return types are given to `Call` as a template function. Without actually performing a cast, `operator()` has no way to know how many values to retrieve and what types to -retrieve them as. Note that multi-value returns must leverage the -`Call` syntax because casting to a tuple of LValues is non-trivial. +retrieve them as. Note that multi-value returns must have `sel::tie` +on the LHS and not `std::tie`. This will create a `sel::Tuple` as +opposed to an `std::tuple` which has the `operator=` implemented for +the selector type. ### Calling Free-standing C++ functions from Lua diff --git a/include/Selector.h b/include/Selector.h index 0c0f5d7..37445c8 100644 --- a/include/Selector.h +++ b/include/Selector.h @@ -4,6 +4,7 @@ #include "State.h" #include #include +#include "Tuple.h" #include "util.h" extern "C" { @@ -106,6 +107,14 @@ class Selector { } void operator=(const char *s) const; + + template + operator std::tuple() const { + _traverse(); + _get(); + (*_functor)(sizeof...(Ret)); + return detail::_pop_n_reset(_state._l); + } operator bool() const; operator int() const; operator unsigned int() const; diff --git a/include/Tuple.h b/include/Tuple.h new file mode 100644 index 0000000..01528ed --- /dev/null +++ b/include/Tuple.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +namespace sel { +template +class Tuple { +private: + std::tuple _tuple; +public: + Tuple(T&... args) : _tuple(args...) {} + + void operator=(const sel::Selector &s) { + _tuple = std::tuple::type...>(s); + } +}; + +template +Tuple tie(T&... args) { + return Tuple(args...); +} +} diff --git a/test/interop_tests.h b/test/interop_tests.h index f26f4ec..b21386d 100644 --- a/test/interop_tests.h +++ b/test/interop_tests.h @@ -24,7 +24,7 @@ bool test_add(sel::State &state) { bool test_multi_return(sel::State &state) { state.Load("../test/test.lua"); int sum, difference; - std::tie(sum, difference) = state["sum_and_difference"].Call(3, 1); + sel::tie(sum, difference) = state["sum_and_difference"](3, 1); return (sum == 4 && difference == 2); } @@ -33,7 +33,7 @@ bool test_heterogeneous_return(sel::State &state) { int x; bool y; std::string z; - std::tie(x, y, z) = state["bar"].Call(); + sel::tie(x, y, z) = state["bar"](); return x == 4 && y == true && z == "hi"; } @@ -114,7 +114,7 @@ bool test_multivalue_c_fun_return(sel::State &state) { state.Load("../test/test.lua"); state["test_fun"] = &my_sum_and_difference; int sum, difference; - std::tie(sum, difference) = state["test_fun"].Call(-2, 2); + sel::tie(sum, difference) = state["test_fun"](-2, 2); return sum == 0 && difference == -4; }