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