1 | #pragma once |
2 | |
3 | #include <tuple> |
4 | |
5 | // Modified from https://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda |
6 | |
7 | // Fallback, anything with an operator() |
8 | template <typename T> |
9 | struct function_traits : public function_traits<decltype(&T::operator())> { |
10 | }; |
11 | |
12 | // Pointers to class members that are themselves functors. |
13 | // For example, in the following code: |
14 | // template <typename func_t> |
15 | // struct S { |
16 | // func_t f; |
17 | // }; |
18 | // template <typename func_t> |
19 | // S<func_t> make_s(func_t f) { |
20 | // return S<func_t> { .f = f }; |
21 | // } |
22 | // |
23 | // auto s = make_s([] (int, float) -> double { /* ... */ }); |
24 | // |
25 | // function_traits<decltype(&s::f)> traits; |
26 | template <typename ClassType, typename T> |
27 | struct function_traits<T ClassType::*> : public function_traits<T> { |
28 | }; |
29 | |
30 | // Const class member functions |
31 | template <typename ClassType, typename ReturnType, typename... Args> |
32 | struct function_traits<ReturnType(ClassType::*)(Args...) const> : public function_traits<ReturnType(Args...)> { |
33 | }; |
34 | |
35 | // Reference types |
36 | template <typename T> |
37 | struct function_traits<T&> : public function_traits<T> {}; |
38 | template <typename T> |
39 | struct function_traits<T*> : public function_traits<T> {}; |
40 | |
41 | // Free functions |
42 | template <typename ReturnType, typename... Args> |
43 | struct function_traits<ReturnType(Args...)> { |
44 | // arity is the number of arguments. |
45 | enum { arity = sizeof...(Args) }; |
46 | |
47 | typedef std::tuple<Args...> ArgsTuple; |
48 | typedef ReturnType result_type; |
49 | |
50 | template <size_t i> |
51 | struct arg |
52 | { |
53 | typedef typename std::tuple_element<i, std::tuple<Args...>>::type type; |
54 | // the i-th argument is equivalent to the i-th tuple element of a tuple |
55 | // composed of those arguments. |
56 | }; |
57 | }; |
58 | |
59 | template <typename T> |
60 | struct nullary_function_traits { |
61 | using traits = function_traits<T>; |
62 | using result_type = typename traits::result_type; |
63 | }; |
64 | |
65 | template <typename T> |
66 | struct unary_function_traits { |
67 | using traits = function_traits<T>; |
68 | using result_type = typename traits::result_type; |
69 | using arg1_t = typename traits::template arg<0>::type; |
70 | }; |
71 | |
72 | template <typename T> |
73 | struct binary_function_traits { |
74 | using traits = function_traits<T>; |
75 | using result_type = typename traits::result_type; |
76 | using arg1_t = typename traits::template arg<0>::type; |
77 | using arg2_t = typename traits::template arg<1>::type; |
78 | }; |
79 | |
80 | |
81 | // Traits for calling with c10::guts::invoke, where member_functions have a first argument of ClassType |
82 | template <typename T> |
83 | struct invoke_traits : public function_traits<T>{ |
84 | }; |
85 | |
86 | template <typename T> |
87 | struct invoke_traits<T&> : public invoke_traits<T>{ |
88 | }; |
89 | |
90 | template <typename T> |
91 | struct invoke_traits<T&&> : public invoke_traits<T>{ |
92 | }; |
93 | |
94 | template <typename ClassType, typename ReturnType, typename... Args> |
95 | struct invoke_traits<ReturnType(ClassType::*)(Args...)> : |
96 | public function_traits<ReturnType(ClassType&, Args...)> { |
97 | }; |
98 | |
99 | template <typename ClassType, typename ReturnType, typename... Args> |
100 | struct invoke_traits<ReturnType(ClassType::*)(Args...) const> : |
101 | public function_traits<ReturnType(const ClassType&, Args...)> { |
102 | }; |
103 | |