Skip to content

Commit

Permalink
Support return type inferencing for multi-return functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremyong committed Jan 27, 2014
1 parent 1b059b5 commit 8871d5c
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 6 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<int, int>(3, 1);
sel::tie(sum, difference) = state["sum_and_difference"](3, 1);
assert(sum == 4 && difference == 2);

// Call function in table
Expand All @@ -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
Expand Down
9 changes: 9 additions & 0 deletions include/Selector.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "State.h"
#include <string>
#include <tuple>
#include "Tuple.h"
#include "util.h"

extern "C" {
Expand Down Expand Up @@ -106,6 +107,14 @@ class Selector {
}

void operator=(const char *s) const;

template <typename... Ret>
operator std::tuple<Ret...>() const {
_traverse();
_get();
(*_functor)(sizeof...(Ret));
return detail::_pop_n_reset<Ret...>(_state._l);
}
operator bool() const;
operator int() const;
operator unsigned int() const;
Expand Down
22 changes: 22 additions & 0 deletions include/Tuple.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include <tuple>

namespace sel {
template <typename... T>
class Tuple {
private:
std::tuple<T&...> _tuple;
public:
Tuple(T&... args) : _tuple(args...) {}

void operator=(const sel::Selector &s) {
_tuple = std::tuple<typename std::remove_reference<T>::type...>(s);
}
};

template <typename... T>
Tuple<T&...> tie(T&... args) {
return Tuple<T&...>(args...);
}
}
6 changes: 3 additions & 3 deletions test/interop_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<int, int>(3, 1);
sel::tie(sum, difference) = state["sum_and_difference"](3, 1);
return (sum == 4 && difference == 2);
}

Expand All @@ -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<int, bool, std::string>();
sel::tie(x, y, z) = state["bar"]();
return x == 4 && y == true && z == "hi";
}

Expand Down Expand Up @@ -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<int, int>(-2, 2);
sel::tie(sum, difference) = state["test_fun"](-2, 2);
return sum == 0 && difference == -4;
}

Expand Down

0 comments on commit 8871d5c

Please sign in to comment.