function_traits.hpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #ifndef BOOST_LEAF_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED
  2. #define BOOST_LEAF_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED
  3. // Copyright 2018-2023 Emil Dotchevski and Reverge Studios, Inc.
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #include <boost/leaf/detail/mp11.hpp>
  7. #include <tuple>
  8. namespace boost { namespace leaf {
  9. namespace leaf_detail
  10. {
  11. template <class T> struct remove_noexcept { using type = T; };
  12. template <class R, class... A> struct remove_noexcept<R(*)(A...) noexcept> { using type = R(*)(A...); };
  13. template <class C, class R, class... A> struct remove_noexcept<R(C::*)(A...) noexcept> { using type = R(C::*)(A...); };
  14. template <class C, class R, class... A> struct remove_noexcept<R(C::*)(A...) const noexcept> { using type = R(C::*)(A...) const; };
  15. template<class...>
  16. struct gcc49_workaround //Thanks Glen Fernandes
  17. {
  18. using type = void;
  19. };
  20. template<class... T>
  21. using void_t = typename gcc49_workaround<T...>::type;
  22. template<class F,class V=void>
  23. struct function_traits_impl
  24. {
  25. constexpr static int arity = -1;
  26. };
  27. template<class F>
  28. struct function_traits_impl<F, void_t<decltype(&F::operator())>>
  29. {
  30. private:
  31. using tr = function_traits_impl<typename remove_noexcept<decltype(&F::operator())>::type>;
  32. public:
  33. using return_type = typename tr::return_type;
  34. static constexpr int arity = tr::arity - 1;
  35. using mp_args = typename leaf_detail_mp11::mp_rest<typename tr::mp_args>;
  36. template <int I>
  37. struct arg:
  38. tr::template arg<I+1>
  39. {
  40. };
  41. };
  42. template<class R, class... A>
  43. struct function_traits_impl<R(A...)>
  44. {
  45. using return_type = R;
  46. static constexpr int arity = sizeof...(A);
  47. using mp_args = leaf_detail_mp11::mp_list<A...>;
  48. template <int I>
  49. struct arg
  50. {
  51. static_assert(I < arity, "I out of range");
  52. using type = typename std::tuple_element<I,std::tuple<A...>>::type;
  53. };
  54. };
  55. template<class F> struct function_traits_impl<F&> : function_traits_impl<F> { };
  56. template<class F> struct function_traits_impl<F&&> : function_traits_impl<F> { };
  57. template<class R, class... A> struct function_traits_impl<R(*)(A...)> : function_traits_impl<R(A...)> { };
  58. template<class R, class... A> struct function_traits_impl<R(* &)(A...)> : function_traits_impl<R(A...)> { };
  59. template<class R, class... A> struct function_traits_impl<R(* const &)(A...)> : function_traits_impl<R(A...)> { };
  60. template<class C, class R, class... A> struct function_traits_impl<R(C::*)(A...)> : function_traits_impl<R(C&,A...)> { };
  61. template<class C, class R, class... A> struct function_traits_impl<R(C::*)(A...) const> : function_traits_impl<R(C const &,A...)> { };
  62. template<class C, class R> struct function_traits_impl<R(C::*)> : function_traits_impl<R(C&)> { };
  63. template <class F>
  64. struct function_traits: function_traits_impl<typename remove_noexcept<F>::type>
  65. {
  66. };
  67. template <class F>
  68. using fn_return_type = typename function_traits<F>::return_type;
  69. template <class F, int I>
  70. using fn_arg_type = typename function_traits<F>::template arg<I>::type;
  71. template <class F>
  72. using fn_mp_args = typename function_traits<F>::mp_args;
  73. }
  74. } }
  75. #endif