]> git.rm.cloudns.org Git - xonotic/netradiant.git/commitdiff
Support lambda callbacks
authorTimePath <andrew.hardaker1995@gmail.com>
Sun, 31 Dec 2017 10:05:49 +0000 (21:05 +1100)
committerTimePath <andrew.hardaker1995@gmail.com>
Sun, 31 Dec 2017 10:05:49 +0000 (21:05 +1100)
libs/generic/callback.h
libs/generic/functional.h
libs/signal/isignal.h

index ef74e0cc90d068411c15f3e1ae106dba754cbf18..4110691e03b6b672ed8bc0917edbc2474c0e1dc9 100644 (file)
@@ -148,7 +148,7 @@ public:
 };
 
 template<class Caller>
-using BindFirstOpaque = BindFirstOpaqueN<Caller, typename Caller::func>;
+using BindFirstOpaque = BindFirstOpaqueN<Caller, get_func<Caller>>;
 
 template<class F>
 class CallbackN;
index 7d76a8b0e5bf17060c38b8aa95564fa03e6593ed..8843e363b8325fd4c870249941bc5049573e6db9 100644 (file)
@@ -1,9 +1,56 @@
 #if !defined( INCLUDED_FUNCTIONAL_H )
 #define INCLUDED_FUNCTIONAL_H
 
+#include <functional>
 #include <tuple>
 
 namespace detail {
+
+    template<int N>
+    struct rank : rank<N - 1> {
+    };
+
+    template<>
+    struct rank<0> {
+    };
+
+    struct get_func {
+
+        template<class T>
+        struct wrapper {
+            using type = T;
+        };
+
+        template<class F>
+        using func_member = wrapper<typename F::func>;
+
+        template<class F>
+        static wrapper<func_member<F>> test(rank<2>) { return {}; }
+
+        template<class F>
+        struct func_lambda {
+            using type = typename func_lambda<decltype(&F::operator())>::type;
+        };
+
+        template<class R, class... Ts>
+        struct func_lambda<R(*)(Ts...)> {
+            using type = R(Ts...);
+        };
+
+        template<class Object, class R, class... Ts>
+        struct func_lambda<R(Object::*)(Ts...) const> {
+            using type = R(Ts...);
+        };
+
+        template<class Object, class R, class... Ts>
+        struct func_lambda<R(Object::*)(Ts...)> {
+            using type = R(Ts...);
+        };
+
+        template<class F, class = func_lambda<F>>
+        static wrapper<func_lambda<F>> test(rank<1>) { return {}; }
+    };
+
     template<class F>
     struct Fn;
 
@@ -17,10 +64,13 @@ namespace detail {
 }
 
 template<class Caller>
-using get_result_type = typename detail::Fn<typename Caller::func>::result_type;
+using get_func = typename decltype(detail::get_func::test<Caller>(detail::rank<2>{}))::type::type;
+
+template<class Caller>
+using get_result_type = typename detail::Fn<get_func<Caller>>::result_type;
 
 template<class Caller, int N>
-using get_argument = typename detail::Fn<typename Caller::func>::template get<N>;
+using get_argument = typename detail::Fn<get_func<Caller>>::template get<N>;
 
 template<class Object, class F>
 class MemberN;
@@ -132,7 +182,7 @@ public:
 };
 
 template<class Functor>
-using FunctorInvoke = FunctorNInvoke<Functor, typename Functor::func>;
+using FunctorInvoke = FunctorNInvoke<Functor, get_func<Functor>>;
 
 template<class Object, class R, R(Object::*member)()>
 using Member = typename MemberN<Object, R()>::template instance<member>;
index c447d71bc13a30a1a12b4508f8c4579267b09c3d..9eaa9d0b2b49e262e5a06b914beb922056a5e3a8 100644 (file)
@@ -37,7 +37,7 @@ public:
 };
 
 template<class Caller>
-using SignalHandlerCaller = SignalHandlerCallerN<Caller, typename Caller::func>;
+using SignalHandlerCaller = SignalHandlerCallerN<Caller, get_func<Caller>>;
 
 template<class Caller>
 using SignalHandlerCaller1 = SignalHandlerCaller<Caller>;