55#include < boost/mp11/algorithm.hpp>
66#include < boost/mp11/utility.hpp>
77
8- #include < functional>
98#include < type_traits>
109#include < utility>
1110
1211namespace stdx {
1312inline namespace v1 {
1413namespace detail {
15- template <typename ...> struct function_traits ;
14+ template <auto > struct any_type {
15+ // NOLINTNEXTLINE(google-explicit-constructor)
16+ template <typename T> operator T ();
17+ };
1618
17- template <typename R, typename ... Args>
18- struct function_traits <std::function<R(Args...)>> {
19+ template <typename F> struct function_traits ;
20+
21+ template <typename R, typename ... Args> struct function_traits <R(Args...)> {
1922 using return_type = R;
2023
2124 template <template <typename ...> typename List> using args = List<Args...>;
2225 template <template <typename ...> typename List>
2326 using decayed_args = List<std::decay_t <Args>...>;
2427 using arity = std::integral_constant<std::size_t , sizeof ...(Args)>;
28+ using obj_t = void ;
2529
2630 template <auto N> using nth_arg = nth_t <N, Args...>;
2731 template <auto N> using decayed_nth_arg = std::decay_t <nth_arg<N>>;
32+
33+ template <std::size_t ... Is>
34+ constexpr static auto invoke (std::index_sequence<Is...>)
35+ -> std::invoke_result_t<R(Args...), any_type<Is>...>;
36+ };
37+
38+ template <typename R, typename ... Args>
39+ struct function_traits <R (*)(Args...)> : function_traits<R(Args...)> {};
40+
41+ template <typename R, typename ... Args>
42+ struct function_traits <R (*const )(Args...)> : function_traits<R(Args...)> {};
43+
44+ template <typename R, typename ... Args>
45+ struct function_traits <R (*volatile )(Args...)> : function_traits<R(Args...)> {};
46+
47+ template <typename R, typename ... Args>
48+ struct function_traits <R (*const volatile )(Args...)>
49+ : function_traits<R(Args...)> {};
50+
51+ template <typename C, typename R, typename ... Args>
52+ struct function_traits <R (C::*)(Args...)> : function_traits<R(Args...)> {
53+ using obj_t = C;
54+ };
55+
56+ template <typename C, typename R, typename ... Args>
57+ struct function_traits <R (C::*)(Args...) &> : function_traits<R(Args...)> {
58+ using obj_t = C &;
59+ };
60+
61+ template <typename C, typename R, typename ... Args>
62+ struct function_traits <R (C::*)(Args...) const &>
63+ : function_traits<R(Args...)> {
64+ using obj_t = C const &;
65+ };
66+
67+ template <typename C, typename R, typename ... Args>
68+ struct function_traits <R (C::*)(Args...) volatile &>
69+ : function_traits<R(Args...)> {
70+ using obj_t = C volatile &;
71+ };
72+
73+ template <typename C, typename R, typename ... Args>
74+ struct function_traits <R (C::*)(Args...) const volatile &>
75+ : function_traits<R(Args...)> {
76+ using obj_t = C const volatile &;
77+ };
78+
79+ template <typename C, typename R, typename ... Args>
80+ struct function_traits <R (C::*)(Args...) &&> : function_traits<R(Args...)> {
81+ using obj_t = C &&;
82+ };
83+
84+ template <typename C, typename R, typename ... Args>
85+ struct function_traits <R (C::*)(Args...) const &&>
86+ : function_traits<R(Args...)> {
87+ using obj_t = C const &&;
88+ };
89+
90+ template <typename C, typename R, typename ... Args>
91+ struct function_traits <R (C::*)(Args...) volatile &&>
92+ : function_traits<R(Args...)> {
93+ using obj_t = C volatile &&;
94+ };
95+
96+ template <typename C, typename R, typename ... Args>
97+ struct function_traits <R (C::*)(Args...) const volatile &&>
98+ : function_traits<R(Args...)> {
99+ using obj_t = C const volatile &&;
100+ };
101+
102+ template <typename C, typename R, typename ... Args>
103+ struct function_traits <R (C::*)(Args...) const > : function_traits<R(Args...)> {
104+ using obj_t = C const ;
105+ };
106+
107+ template <typename C, typename R, typename ... Args>
108+ struct function_traits <R (C::*)(Args...) volatile >
109+ : function_traits<R(Args...)> {
110+ using obj_t = C volatile ;
28111};
29- } // namespace detail
30112
113+ template <typename C, typename R, typename ... Args>
114+ struct function_traits <R (C::*)(Args...) const volatile >
115+ : function_traits<R(Args...)> {
116+ using obj_t = C const volatile ;
117+ };
118+
119+ template <typename F, typename = void > struct detect_call_operator {
120+ template <std::size_t ... Is>
121+ constexpr static auto invoke (std::index_sequence<Is...>) ->
122+ typename boost::mp11::mp_cond<
123+ boost::mp11::mp_valid<std::invoke_result_t, F &&, any_type<Is>...>,
124+ boost::mp11::mp_defer<std::invoke_result_t, F &&, any_type<Is>...>,
125+ boost::mp11::mp_valid<std::invoke_result_t, F &, any_type<Is>...>,
126+ boost::mp11::mp_defer<std::invoke_result_t, F &,
127+ any_type<Is>...>>::type;
128+ };
31129template <typename F>
32- using function_traits =
33- detail::function_traits<decltype (std::function{std::declval<F>()})>;
130+ struct detect_call_operator <
131+ F, std::void_t <decltype (&remove_cvref_t <F>::operator ())>>
132+ : function_traits<decltype (&remove_cvref_t <F>::operator ())> {};
133+
134+ template <typename F> struct function_traits : detect_call_operator<F> {};
135+ } // namespace detail
136+
137+ template <typename F> using function_traits = detail::function_traits<F>;
34138
35139template <typename F> using return_t = typename function_traits<F>::return_type;
36140template <typename F, template <typename ...> typename List>
@@ -39,6 +143,7 @@ template <typename F, template <typename...> typename List>
39143using decayed_args_t = typename function_traits<F>::template decayed_args<List>;
40144template <typename F>
41145using nongeneric_arity_t = typename function_traits<F>::arity;
146+ template <typename F> using obj_arg_t = typename function_traits<F>::obj_t ;
42147
43148template <typename F, auto N>
44149using nth_arg_t = typename function_traits<F>::template nth_arg<N>;
@@ -47,18 +152,9 @@ using decayed_nth_arg_t =
47152 typename function_traits<F>::template decayed_nth_arg<N>;
48153
49154namespace detail {
50- template <auto > struct any_type {
51- // NOLINTNEXTLINE(google-explicit-constructor)
52- template <typename T> operator T ();
53- };
54-
55- template <typename F, std::size_t ... Is>
56- constexpr auto try_invoke_impl (std::index_sequence<Is...>)
57- -> std::invoke_result_t<F, any_type<Is>...>;
58-
59155template <typename F, typename N>
60156using try_invoke =
61- decltype (try_invoke_impl <F>(std::make_index_sequence<N::value>{}));
157+ decltype (function_traits <F>::invoke (std::make_index_sequence<N::value>{}));
62158
63159template <typename F, typename N>
64160using has_arg_count = boost::mp11::mp_valid<try_invoke, F, N>;
0 commit comments