summaryrefslogtreecommitdiff
path: root/src/util/BindMethod.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/BindMethod.hxx')
-rw-r--r--src/util/BindMethod.hxx85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/util/BindMethod.hxx b/src/util/BindMethod.hxx
index 451750121..f02e36d52 100644
--- a/src/util/BindMethod.hxx
+++ b/src/util/BindMethod.hxx
@@ -172,6 +172,70 @@ MakeBindMethodWrapper()
return BindMethodWrapperGenerator<T, typename MethodWithSignature<T, S>::method_pointer, method, S>::Invoke;
}
+/**
+ * Helper class which introspects a function pointer type.
+ *
+ * @param S the function type
+ */
+template<typename S>
+struct FunctionTraits;
+
+template<typename R, typename... Args>
+struct FunctionTraits<R(Args...)> {
+ /**
+ * A function type which describes the "plain" function
+ * signature.
+ */
+ typedef R function_type(Args...);
+
+ /**
+ * A function pointer type which describes the "plain"
+ * function signature.
+ */
+ typedef R (*pointer_type)(Args...);
+};
+
+/**
+ * Generate a wrapper function for a plain function which ignores the
+ * instance pointer. Helper class for
+ * #BindFunctionWrapperGenerator.
+ *
+ * @param F the function pointer type
+ * @param function the function pointer
+ * @param R the return type
+ * @param Args the function arguments
+ */
+template<typename F, F function, typename R, typename... Args>
+struct BindFunctionWrapperGenerator2 {
+ static R Invoke(void *, Args... args) {
+ return function(std::forward<Args>(args)...);
+ }
+};
+
+/**
+ * Generate a wrapper function.
+ *
+ * @param S the plain function signature type
+ * @param P the plain function pointer type
+ * @param function the function pointer
+ */
+template<typename S, typename P, P function>
+struct BindFunctionWrapperGenerator;
+
+template<typename P, P function, typename R, typename... Args>
+struct BindFunctionWrapperGenerator<R(Args...), P, function>
+ : BindFunctionWrapperGenerator2<P, function, R, Args...> {
+};
+
+template<typename T, typename T::pointer_type function>
+typename MethodWrapperWithSignature<typename T::function_type>::function_pointer
+MakeBindFunctionWrapper()
+{
+ return BindFunctionWrapperGenerator<typename T::function_type,
+ typename T::pointer_type,
+ function>::Invoke;
+}
+
} /* namespace BindMethodDetail */
/**
@@ -206,4 +270,25 @@ BindMethod(T &_instance)
*/
#define BIND_THIS_METHOD(method) BIND_METHOD(*this, &std::remove_reference<decltype(*this)>::type::method)
+/**
+ * Construct a #BoundMethod instance for a plain function.
+ *
+ * @param T the #FunctionTraits class
+ * @param function the function pointer
+ */
+template<typename T, typename T::pointer_type function>
+constexpr BoundMethod<typename T::function_type>
+BindFunction()
+{
+ return BoundMethod<typename T::function_type>(nullptr,
+ BindMethodDetail::MakeBindFunctionWrapper<T, function>());
+}
+
+/**
+ * Shortcut macro which takes a function pointer and constructs a
+ * #BoundMethod instance.
+ */
+#define BIND_FUNCTION(function) \
+ BindFunction<typename BindMethodDetail::FunctionTraits<decltype(function)>, &function>()
+
#endif