Skip to content

Commit

Permalink
Ensure argument transparency.
Browse files Browse the repository at this point in the history
  • Loading branch information
ThePhD committed Apr 18, 2016
1 parent 062d228 commit 96da27d
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 11 deletions.
12 changes: 6 additions & 6 deletions sol/stack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,18 @@ inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 1) {

template <bool checkargs = default_check_arguments, std::size_t... I, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
inline decltype(auto) call(types<R>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
typedef meta::index_in_pack<this_state, Args...> state_pack_index;
typedef std::integral_constant<int, state_pack_index::value == -1 ? INT_MAX : static_cast<int>(state_pack_index::value)> state_idx;
typedef meta::index_in_pack<this_state, Args...> state_index;
typedef meta::index_in_pack<variadic_args, Args...> va_pack_index;
check_types<checkargs>{}.check(ta, tai, L, start, type_panic);
return fx(std::forward<FxArgs>(args)..., stack_detail::unchecked_get<Args>(L, start + (state_idx::value < I ? I - 1 : I))...);
return fx(std::forward<FxArgs>(args)..., stack_detail::unchecked_get<Args>(L, start + I - static_cast<int>(state_index::value < I) - static_cast<int>(va_pack_index::value < I))...);
}

template <bool checkargs = default_check_arguments, std::size_t... I, typename... Args, typename Fx, typename... FxArgs>
inline void call(types<void>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
typedef meta::index_in_pack<this_state, Args...> state_pack_index;
typedef std::integral_constant<int, state_pack_index::value == -1 ? INT_MAX : static_cast<int>(state_pack_index::value)> state_idx;
typedef meta::index_in_pack<this_state, Args...> state_index;
typedef meta::index_in_pack<variadic_args, Args...> va_pack_index;
check_types<checkargs>{}.check(ta, tai, L, start, type_panic);
fx(std::forward<FxArgs>(args)..., stack_detail::unchecked_get<Args>(L, start + (state_idx::value < I ? I - 1 : I))...);
fx(std::forward<FxArgs>(args)..., stack_detail::unchecked_get<Args>(L, start + I - static_cast<int>(state_index::value < I) - static_cast<int>(va_pack_index::value < I))...);
}
} // stack_detail

Expand Down
8 changes: 4 additions & 4 deletions sol/stack_check.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ struct basic_check {

template <bool b>
struct check_types {
template <std::size_t I0, std::size_t... I, typename Arg0, typename... Args, typename Handler>
static bool check(types<Arg0, Args...>, std::index_sequence<I0, I...>, lua_State* L, int firstargument, Handler&& handler) {
if (!stack::check<Arg0>(L, firstargument + I0, handler))
template <std::size_t I0, std::size_t... I, typename T, typename... Args, typename Handler>
static bool check(types<T, Args...>, std::index_sequence<I0, I...>, lua_State* L, int firstargument, Handler&& handler) {
if (!stack::check<T>(L, firstargument + I0, handler))
return false;
return check(types<Args...>(), std::index_sequence<I...>(), L, firstargument - static_cast<int>(std::is_same<this_state, meta::Unqualified<Arg0>>::value), std::forward<Handler>(handler));
return check(types<Args...>(), std::index_sequence<I...>(), L, firstargument - static_cast<int>(is_transparent_argument<meta::Unqualified<T>>::value), std::forward<Handler>(handler));
}

template <typename Handler>
Expand Down
2 changes: 1 addition & 1 deletion sol/traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ struct find_in_pack_v<V, Vs1, Vs...> : Or<Bool<(V::value == Vs1::value)>, find_i

namespace meta_detail {
template<std::size_t I, typename T, typename... Args>
struct index_in_pack : std::integral_constant<std::ptrdiff_t, -1> { };
struct index_in_pack : std::integral_constant<std::size_t, SIZE_MAX> { };

template<std::size_t I, typename T, typename T1, typename... Args>
struct index_in_pack<I, T, T1, Args...> : std::conditional_t<std::is_same<T, T1>::value, std::integral_constant<std::ptrdiff_t, I>, index_in_pack<I + 1, T, Args...>> { };
Expand Down
11 changes: 11 additions & 0 deletions sol/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,8 @@ using lightuserdata = basic_lightuserdata<reference>;
using stack_lightuserdata = basic_lightuserdata<stack_reference>;
class coroutine;
class thread;
struct variadic_args;
struct this_state;

template <typename T, typename = void>
struct lua_type_of : std::integral_constant<type, type::userdata> {};
Expand Down Expand Up @@ -434,6 +436,15 @@ struct is_proxy_primitive : is_lua_primitive<T> { };
template <typename T>
struct is_unique_usertype : std::false_type {};

template <typename T>
struct is_transparent_argument : std::false_type {};

template <>
struct is_transparent_argument<this_state> : std::true_type {};

template <>
struct is_transparent_argument<variadic_args> : std::true_type {};

template<typename T>
inline type type_of() {
return lua_type_of<meta::Unqualified<T>>::value;
Expand Down
8 changes: 8 additions & 0 deletions test_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -781,3 +781,11 @@ TEST_CASE("functions/variadic_args", "Check to see we can receive multiple argum
REQUIRE(lx2.b);
REQUIRE_FALSE(lx3.b);
}

TEST_CASE("functions/required_and_variadic_args", "Check if a certain number of arguments can still be required even when using variadic_args") {
sol::state lua;
lua.set_function("v", [](sol::this_state, sol::variadic_args, int, int) {});
REQUIRE_NOTHROW(lua.script("v(20, 25, 30)"));
REQUIRE_NOTHROW(lua.script("v(20, 25)"));
REQUIRE_THROWS(lua.script("v(20)"));
}

0 comments on commit 96da27d

Please sign in to comment.