+
+ 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 {}; }
+ };
+