File indexing completed on 2025-01-18 09:39:11
0001 #ifndef BOOST_LEAF_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED
0002 #define BOOST_LEAF_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED
0003
0004
0005
0006
0007
0008
0009 #include <boost/leaf/detail/mp11.hpp>
0010
0011 #include <tuple>
0012
0013 namespace boost { namespace leaf {
0014
0015 namespace leaf_detail
0016 {
0017 template <class T> struct remove_noexcept { using type = T; };
0018 template <class R, class... A> struct remove_noexcept<R(*)(A...) noexcept> { using type = R(*)(A...); };
0019 template <class C, class R, class... A> struct remove_noexcept<R(C::*)(A...) noexcept> { using type = R(C::*)(A...); };
0020 template <class C, class R, class... A> struct remove_noexcept<R(C::*)(A...) const noexcept> { using type = R(C::*)(A...) const; };
0021
0022 template<class...>
0023 struct gcc49_workaround
0024 {
0025 using type = void;
0026 };
0027
0028 template<class... T>
0029 using void_t = typename gcc49_workaround<T...>::type;
0030
0031 template<class F,class V=void>
0032 struct function_traits_impl
0033 {
0034 constexpr static int arity = -1;
0035 };
0036
0037 template<class F>
0038 struct function_traits_impl<F, void_t<decltype(&F::operator())>>
0039 {
0040 private:
0041
0042 using tr = function_traits_impl<typename remove_noexcept<decltype(&F::operator())>::type>;
0043
0044 public:
0045
0046 using return_type = typename tr::return_type;
0047 static constexpr int arity = tr::arity - 1;
0048
0049 using mp_args = typename leaf_detail_mp11::mp_rest<typename tr::mp_args>;
0050
0051 template <int I>
0052 struct arg:
0053 tr::template arg<I+1>
0054 {
0055 };
0056 };
0057
0058 template<class R, class... A>
0059 struct function_traits_impl<R(A...)>
0060 {
0061 using return_type = R;
0062 static constexpr int arity = sizeof...(A);
0063
0064 using mp_args = leaf_detail_mp11::mp_list<A...>;
0065
0066 template <int I>
0067 struct arg
0068 {
0069 static_assert(I < arity, "I out of range");
0070 using type = typename std::tuple_element<I,std::tuple<A...>>::type;
0071 };
0072 };
0073
0074 template<class F> struct function_traits_impl<F&> : function_traits_impl<F> { };
0075 template<class F> struct function_traits_impl<F&&> : function_traits_impl<F> { };
0076 template<class R, class... A> struct function_traits_impl<R(*)(A...)> : function_traits_impl<R(A...)> { };
0077 template<class R, class... A> struct function_traits_impl<R(* &)(A...)> : function_traits_impl<R(A...)> { };
0078 template<class R, class... A> struct function_traits_impl<R(* const &)(A...)> : function_traits_impl<R(A...)> { };
0079 template<class C, class R, class... A> struct function_traits_impl<R(C::*)(A...)> : function_traits_impl<R(C&,A...)> { };
0080 template<class C, class R, class... A> struct function_traits_impl<R(C::*)(A...) const> : function_traits_impl<R(C const &,A...)> { };
0081 template<class C, class R> struct function_traits_impl<R(C::*)> : function_traits_impl<R(C&)> { };
0082
0083 template <class F>
0084 struct function_traits: function_traits_impl<typename remove_noexcept<F>::type>
0085 {
0086 };
0087
0088 template <class F>
0089 using fn_return_type = typename function_traits<F>::return_type;
0090
0091 template <class F, int I>
0092 using fn_arg_type = typename function_traits<F>::template arg<I>::type;
0093
0094 template <class F>
0095 using fn_mp_args = typename function_traits<F>::mp_args;
0096 }
0097
0098 } }
0099
0100 #endif