github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/3rd_party/fflib/include/ff/util/function_traits.h (about) 1 /*********************************************** 2 The MIT License (MIT) 3 4 Copyright (c) 2012 Athrun Arthur <athrunarthur@gmail.com> 5 6 Permission is hereby granted, free of charge, to any person obtaining a copy 7 of this software and associated documentation files (the "Software"), to deal 8 in the Software without restriction, including without limitation the rights 9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 copies of the Software, and to permit persons to whom the Software is 11 furnished to do so, subject to the following conditions: 12 13 The above copyright notice and this permission notice shall be included in 14 all copies or substantial portions of the Software. 15 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 THE SOFTWARE. 23 *************************************************/ 24 #pragma once 25 #include "ff/util/func_type_checker.h" 26 #include "ff/util/is_callable.h" 27 #include <functional> 28 #include <type_traits> 29 30 namespace ff { 31 namespace util { 32 template <class F> 33 struct deduce_function {}; 34 35 template <class Ret, class C, class... Args> 36 struct deduce_function<Ret (C::*)(Args...) const> { 37 typedef std::function<Ret(Args...)> type; 38 typedef Ret ret_type; 39 }; 40 41 template <class Ret, class C, class... Args> 42 struct deduce_function<Ret (C::*)(Args...)> { 43 typedef std::function<Ret(Args...)> type; 44 typedef Ret ret_type; 45 }; 46 47 template <class Ret, class... Args> 48 struct deduce_function<Ret(Args...)> { 49 typedef std::function<Ret(Args...)> type; 50 typedef Ret ret_type; 51 }; 52 53 template <class F> 54 struct is_no_args_function { 55 const static bool value = false; 56 }; 57 58 template <class Ret, class C> 59 struct is_no_args_function<Ret (C::*)(void) const> { 60 const static bool value = true; 61 }; 62 63 template <class Ret, class C> 64 struct is_no_args_function<Ret (C::*)(void)> { 65 const static bool value = true; 66 }; 67 68 template <class Ret> 69 struct is_no_args_function<Ret(void)> { 70 const static bool value = true; 71 }; 72 template <class Ret> 73 struct is_no_args_function<Ret (*)(void)> { 74 const static bool value = true; 75 }; 76 77 template <class F, bool flag> 78 struct functor_res_traits { 79 typedef typename deduce_function<decltype( 80 &std::remove_reference<F>::type::operator())>::ret_type ret_type; 81 }; 82 83 template <class F> 84 struct functor_res_traits<F, false> { 85 typedef void ret_type; 86 }; 87 88 template <class F, bool flag> 89 struct bind_res_traits { 90 typedef typename F::result_type ret_type; 91 }; 92 93 template <class F> 94 struct bind_res_traits<F, false> { 95 typedef void ret_type; 96 }; 97 98 namespace internal { 99 template <class F, bool flag> 100 struct function_res_traits_impl { 101 typedef typename deduce_function<F>::ret_type ret_type; 102 }; 103 template <class F> 104 struct function_res_traits_impl<F, false> { 105 typedef void ret_type; 106 }; 107 108 template <class F> 109 struct function_res_traits_impl<F *, true> { 110 typedef typename deduce_function<F>::ret_type ret_type; 111 }; 112 template <class F> 113 struct function_res_traits_impl<F &, true> { 114 typedef typename deduce_function<F>::ret_type ret_type; 115 }; 116 } // namespace internal 117 118 template <class F> 119 struct function_res_traits { 120 typedef typename std::remove_reference<F>::type FT; 121 const static bool s_is_class = std::is_class<FT>::value; 122 const static bool s_is_bind_expr = std::is_bind_expression<FT>::value; 123 124 typedef typename std::conditional< 125 s_is_class, 126 typename std::conditional< 127 s_is_bind_expr, 128 typename bind_res_traits<FT, s_is_bind_expr>::ret_type, 129 typename functor_res_traits<FT, !s_is_bind_expr && 130 s_is_class>::ret_type>::type, 131 typename internal::function_res_traits_impl<FT, !s_is_class>::ret_type>:: 132 type ret_type; 133 }; 134 135 template <class F, bool flag> 136 struct functor_args_traits { 137 const static bool is_no_args = is_no_args_function<decltype( 138 &std::remove_reference<F>::type::operator())>::value; 139 }; 140 141 template <class F> 142 struct functor_args_traits<F, false> { 143 const static bool is_no_args = false; 144 }; 145 146 namespace internal { 147 template <class F, bool flag> 148 struct function_args_traits_impl { 149 const static bool is_no_args = is_no_args_function<F>::value; 150 }; 151 152 template <class F> 153 struct function_args_traits_impl<F, false> { 154 const static bool is_no_args = false; 155 }; 156 157 template <class F> 158 struct function_args_traits_impl<F *, true> { 159 const static bool is_no_args = is_no_args_function<F>::value; 160 }; 161 template <class F> 162 struct function_args_traits_impl<F &, true> { 163 const static bool is_no_args = is_no_args_function<F>::value; 164 }; 165 } // namespace internal 166 167 template <class F> 168 struct function_args_traits { 169 typedef typename std::remove_reference<F>::type FT; 170 const static bool s_is_class = std::is_class<FT>::value; 171 172 const static bool is_no_args = 173 functor_args_traits<FT, s_is_class>::is_no_args || 174 internal::function_args_traits_impl<FT, !s_is_class>::is_no_args; 175 }; 176 177 } // end namespace util 178 }; // end namespace ff