Quellcode durchsuchen

Sort out template mess around 'apply'

Ole vor 9 Jahren
Ursprung
Commit
e0f8c08d6a
3 geänderte Dateien mit 17 neuen und 71 gelöschten Zeilen
  1. 6 0
      lib/luwra/internal.hpp
  2. 8 71
      lib/luwra/stack.hpp
  3. 3 0
      tests/stack.cpp

+ 6 - 0
lib/luwra/internal.hpp

@@ -19,10 +19,16 @@ namespace internal {
 	// Information about function signature
 	template <typename R, typename... A>
 	struct CallableInfo<R(A...)> {
+		// A call to an instance would evaluate to this type
 		using ReturnType = R;
 
+		// Pass the template parameter pack to another template
 		template <template <typename...> class T>
 		using RelayArguments = T<A...>;
+
+		// Pass the signature of this callable to another template
+		template <template <typename> class T>
+		using RelaySignature = T<R(A...)>;
 	};
 
 	// Information about function pointers

+ 8 - 71
lib/luwra/stack.hpp

@@ -9,6 +9,7 @@
 
 #include "common.hpp"
 #include "types.hpp"
+#include "internal.hpp"
 
 #include <cassert>
 #include <utility>
@@ -107,77 +108,17 @@ typename internal::Layout<S>::ReturnType direct(State* state, F&& hook, A&&... a
 	);
 }
 
-namespace internal {
-	template <typename T>
-	struct FunctionObjectHelper {
-		static_assert(sizeof(T) == -1, "Invalid template parameter to FunctionObjectHelper");
-	};
-
-	template <typename T, typename R, typename... A>
-	struct FunctionObjectHelper<R (T::*)(A...)> {
-		using Signature = R(A...);
-		using ReturnType = R;
-	};
-
-	template <typename T, typename R, typename... A>
-	struct FunctionObjectHelper<R (T::*)(A...) const>:
-		FunctionObjectHelper<R (T::*)(A...)>
-	{};
-
-	template <typename T, typename R, typename... A>
-	struct FunctionObjectHelper<R (T::*)(A...) volatile>:
-		FunctionObjectHelper<R (T::*)(A...)>
-	{};
-
-	template <typename T, typename R, typename... A>
-	struct FunctionObjectHelper<R (T::*)(A...) const volatile>:
-		FunctionObjectHelper<R (T::*)(A...)>
-	{};
-
-	template <typename T>
-	using FunctionObjectLayout =
-		Layout<typename FunctionObjectHelper<decltype(&T::operator ())>::Signature>;
-
-	template <typename T>
-	using FunctionObjectReturnType =
-		typename FunctionObjectHelper<decltype(&T::operator ())>::ReturnType;
-}
-
-/**
- * A version of [direct](@ref direct) which is specialized for function pointers; therefore allows
- * you to omit the template parameters since the compiler can infer its parameter and return types.
- */
-template <typename R, typename... A> static inline
-R apply(State* state, int pos, R (* fun)(A...)) {
-	return internal::Layout<R(A...)>::direct(
-		state,
-		pos,
-		fun
-	);
-}
-
-/**
- * Same as `apply(state, 1, fun)`.
- */
-template <typename R, typename... A> static inline
-R apply(State* state, R (* fun)(A...)) {
-	return internal::Layout<R(A...)>::direct(
-		state,
-		1,
-		fun
-	);
-}
-
 /**
  * A version of [direct](@ref direct) which tries to infer the stack layout from the given
- * `Callable`.
+ * `Callable`. It allows you to omit the template parameters since the compiler is able to infer the
+ * parameter and return types.
  */
 template <typename T> static inline
-internal::FunctionObjectReturnType<T> apply(State* state, int pos, const T& obj) {
-	return internal::FunctionObjectLayout<T>::direct(
+typename internal::CallableInfo<T>::ReturnType apply(State* state, int pos, T&& obj) {
+	return internal::CallableInfo<T>::template RelaySignature<internal::Layout>::direct(
 		state,
 		pos,
-		obj
+		std::forward<T>(obj)
 	);
 }
 
@@ -185,12 +126,8 @@ internal::FunctionObjectReturnType<T> apply(State* state, int pos, const T& obj)
  * Same as `apply(state, 1, obj)`.
  */
 template <typename T> static inline
-internal::FunctionObjectReturnType<T> apply(State* state, const T& obj) {
-	return internal::FunctionObjectLayout<T>::direct(
-		state,
-		1,
-		obj
-	);
+typename internal::CallableInfo<T>::ReturnType apply(State* state, T&& obj) {
+	return apply(state, 1, std::forward<T>(obj));
 }
 
 namespace internal {

+ 3 - 0
tests/stack.cpp

@@ -29,6 +29,8 @@ TEST_CASE("StackInteraction") {
 	// Absolute index
 	REQUIRE(luwra::apply(state, test_function_1) == -1);
 	REQUIRE(luwra::apply(state, 1, test_function_1) == -1);
+	REQUIRE(luwra::apply(state, [](int a, int b) -> int { return a - b; }) == -1);
+	REQUIRE(luwra::apply(state, 2, [](int a, int b) -> int { return a + b; }) == 6);
 	REQUIRE(luwra::apply(state, test_function_2) == 9);
 	REQUIRE(luwra::apply(state, 1, test_function_2) == 9);
 
@@ -36,4 +38,5 @@ TEST_CASE("StackInteraction") {
 	REQUIRE(luwra::apply(state, -2, test_function_1) == -2);
 	REQUIRE(luwra::apply(state, -3, test_function_1) == -1);
 	REQUIRE(luwra::apply(state, -3, test_function_2) == 9);
+	REQUIRE(luwra::apply(state, -3, [](int a, int b, int c) -> int { return a - b + c; }) == 3);
 }