aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/function.hpp11
-rw-r--r--src/util/function.tpp75
2 files changed, 86 insertions, 0 deletions
diff --git a/src/util/function.hpp b/src/util/function.hpp
new file mode 100644
index 0000000..13f5356
--- /dev/null
+++ b/src/util/function.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+template <typename>
+struct Signature
+{
+};
+
+template <typename Function>
+constexpr auto normalize_lambda(Function &&func) noexcept;
+
+#include "function.tpp"
diff --git a/src/util/function.tpp b/src/util/function.tpp
new file mode 100644
index 0000000..6ff939b
--- /dev/null
+++ b/src/util/function.tpp
@@ -0,0 +1,75 @@
+#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)));
+}