aboutsummaryrefslogtreecommitdiff
path: root/src/util/function_impl.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/function_impl.hpp')
-rw-r--r--src/util/function_impl.hpp76
1 files changed, 76 insertions, 0 deletions
diff --git a/src/util/function_impl.hpp b/src/util/function_impl.hpp
new file mode 100644
index 0000000..9d3d38c
--- /dev/null
+++ b/src/util/function_impl.hpp
@@ -0,0 +1,76 @@
+#pragma once
+
+#include "function.hpp"
+
+#include <utility>
+
+template <typename>
+struct remove_cv_seq;
+
+template <typename Return, typename... Args>
+struct remove_cv_seq<Return(Args...)>
+{
+ using type = Return(Args...);
+};
+
+template <typename Return, typename... Args>
+struct remove_cv_seq<Return(Args...) const>
+{
+ using type = Return(Args...);
+};
+
+template <typename Return, typename... Args>
+struct remove_cv_seq<Return(Args...) &>
+{
+ using type = Return(Args...);
+};
+
+template <typename Function>
+constexpr inline auto extract_signature(Function * /*unused*/) noexcept
+{
+ return Signature<typename remove_cv_seq<Function>::type>();
+}
+
+template <typename Class, typename Function>
+constexpr inline auto extract_signature(Function Class::* /*unused*/) noexcept
+{
+ return Signature<typename remove_cv_seq<Function>::type>();
+}
+
+template <typename Function>
+constexpr inline auto extract_signature(Function const & /*unused*/) noexcept
+ -> decltype(&Function::operator(), extract_signature(&Function::operator()))
+{
+ return extract_signature(&Function::operator());
+}
+
+template <typename Function, typename Return, typename... Args>
+inline auto
+get_normalized_lambda(Function &&func, Signature<Return(Args...)> /*unused*/) noexcept
+{
+ // Static copy of func. This will make it accessible for the lambda without using a
+ // lamda capture
+ static auto static_func = Function(std::forward<Function>(func));
+
+ return +[](Args... args) noexcept(
+ noexcept(std::declval<Function>()(std::forward<Args>(args)...))) -> Return
+ {
+ return static_func(std::forward<Args>(args)...);
+ };
+}
+
+/**
+ * Normalizes the type signature of a lambda function.
+ *
+ * This will make a lambda with captures passable to other functions.
+ *
+ * @param func A lambda function
+ * @returns The lambda function normalized.
+ */
+template <typename Function>
+constexpr auto normalize_lambda(Function &&func) noexcept
+{
+ return get_normalized_lambda(
+ std::forward<Function>(func),
+ extract_signature(std::forward<Function>(func)));
+}