zhangmeng
2021-07-02 056f71f24cefaf88f2a93714c6678c03ed5f1e0e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#ifndef BOOST_LEAF_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED
#define BOOST_LEAF_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED
 
// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
 
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 
#ifndef BOOST_LEAF_ENABLE_WARNINGS
#   if defined(__clang__)
#       pragma clang system_header
#   elif (__GNUC__*100+__GNUC_MINOR__>301)
#       pragma GCC system_header
#   elif defined(_MSC_VER)
#       pragma warning(push,1)
#   endif
#endif
 
#include <boost/leaf/detail/mp11.hpp>
#include <tuple>
 
namespace boost { namespace leaf {
 
    namespace leaf_detail
    {
        template<class...>
        struct gcc49_workaround //Thanks Glen Fernandes
        {
            using type = void;
        };
 
        template<class... T>
        using void_t = typename gcc49_workaround<T...>::type;
 
        template<class F,class V=void>
        struct function_traits
        {
            constexpr static int arity = -1;
        };
 
        template<class F>
        struct function_traits<F, void_t<decltype(&F::operator())>>
        {
        private:
 
            using tr = function_traits<decltype(&F::operator())>;
 
        public:
 
            using return_type = typename tr::return_type;
            static constexpr int arity = tr::arity - 1;
 
            using mp_args = typename leaf_detail_mp11::mp_rest<typename tr::mp_args>;
 
            template <int I>
            struct arg:
                tr::template arg<I+1>
            {
            };
        };
 
        template<class R, class... A>
        struct function_traits<R(A...)>
        {
            using return_type = R;
            static constexpr int arity = sizeof...(A);
 
            using mp_args = leaf_detail_mp11::mp_list<A...>;
 
            template <int I>
            struct arg
            {
                static_assert(I < arity, "I out of range");
                using type = typename std::tuple_element<I,std::tuple<A...>>::type;
            };
        };
 
        template<class F> struct function_traits<F&> : function_traits<F> { };
        template<class F> struct function_traits<F&&> : function_traits<F> { };
        template<class R, class... A> struct function_traits<R(*)(A...)> : function_traits<R(A...)> { };
        template<class R, class... A> struct function_traits<R(* &)(A...)> : function_traits<R(A...)> { };
        template<class R, class... A> struct function_traits<R(* const &)(A...)> : function_traits<R(A...)> { };
        template<class C, class R, class... A> struct function_traits<R(C::*)(A...)> : function_traits<R(C&,A...)> { };
        template<class C, class R, class... A> struct function_traits<R(C::*)(A...) const> : function_traits<R(C const &,A...)> { };
        template<class C, class R> struct function_traits<R(C::*)> : function_traits<R(C&)> { };
 
        template <class F>
        using fn_return_type = typename function_traits<F>::return_type;
 
        template <class F, int I>
        using fn_arg_type = typename function_traits<F>::template arg<I>::type;
 
        template <class F>
        using fn_mp_args = typename function_traits<F>::mp_args;
 
    }
 
} }
 
#endif