siplasplas
A library for C++ reflection and introspection
function_traits.hpp
1 #ifndef SIPLASPLAS_UTILITY_FUNCTION_TRAITS_HPP
2 #define SIPLASPLAS_UTILITY_FUNCTION_TRAITS_HPP
3 
4 #include "meta.hpp"
5 #include <type_traits>
6 #include <ctti/type_id.hpp>
7 
8 namespace cpp
9 {
10 
11 enum class FunctionKind
12 {
13  INVALID,
14  FREE_FUNCTION,
15  MEMBER_FUNCTION,
16  CONST_MEMBER_FUNCTION,
17  FUNCTOR
18 };
19 
20 namespace detail
21 {
22  /*
23  * With VS2015 we still cannot use expression sfinae to check for operator(),
24  * so here we define a trait in the old way
25  */
26  template<typename T>
27  struct IsFunctorClass
28  {
29  template<typename U>
30  static std::true_type check(decltype(&U::operator(), nullptr));
31  template<typename U>
32  static std::false_type check(...);
33 
34  static constexpr bool value = decltype(check<T>(nullptr))::value;
35  };
36 
37  template<typename Function>
38  struct get_function_signature
39  {
40  static constexpr FunctionKind kind = FunctionKind::INVALID;
41  };
42 
43  template<typename R, typename... Args>
44  struct get_function_signature<R(Args...)>
45  {
46  using args = meta::list<Args...>;
47  using return_type = R;
48 
49  static constexpr FunctionKind kind = FunctionKind::FREE_FUNCTION;
50  };
51 
52  template<typename C, typename R, typename... Args>
53  struct get_function_signature<R (C::*)(Args...)> :
54  get_function_signature<R(Args...)>
55  {
56  static constexpr FunctionKind kind = FunctionKind::MEMBER_FUNCTION;
57  };
58 
59  template<typename C, typename R, typename... Args>
60  struct get_function_signature<R (C::*)(Args...) const> :
61  get_function_signature<R(Args...)>
62  {
63  static constexpr FunctionKind kind = FunctionKind::CONST_MEMBER_FUNCTION;
64  };
65 
66 }
67 
68 template<typename Function, bool IsFunctor = detail::IsFunctorClass<Function>::value>
69 struct function_signature : public
70  detail::get_function_signature<Function>
71 {};
72 
73 template<typename Functor>
74 struct function_signature<Functor, true> :
75  detail::get_function_signature<decltype(&Functor::operator())>
76 {
77  static constexpr FunctionKind kind = FunctionKind::FUNCTOR;
78 };
79 
80 template<typename Function>
81 using function_return_type = typename function_signature<Function>::return_type;
82 
83 template<typename Function>
84 using function_arguments = typename function_signature<Function>::args;
85 
86 template<std::size_t Index, typename Function>
87 using function_argument = meta::get_t<Index, function_arguments<Function>>;
88 
89 template<typename Function>
90 constexpr FunctionKind function_kind()
91 {
92  return function_signature<Function>::kind;
93 }
94 
95 template<typename Function>
96 constexpr FunctionKind function_kind(Function)
97 {
98  return function_kind<Function>();
99 }
100 
101 template<typename A, typename B>
102 struct equal_signature : std::is_same<
103  function_arguments<A>, function_arguments<B>
104 >{};
105 
106 }
107 
108 #endif // SIPLASPLAS_UTILITY_FUNCTION_TRAITS_HPP
Definition: canary_allocator.hpp:7