function_traits.hpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #ifndef BOOST_LEAF_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED
  2. #define BOOST_LEAF_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED
  3. /// Copyright (c) 2018-2021 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. #ifndef BOOST_LEAF_ENABLE_WARNINGS ///
  7. # if defined(_MSC_VER) ///
  8. # pragma warning(push,1) ///
  9. # elif defined(__clang__) ///
  10. # pragma clang system_header ///
  11. # elif (__GNUC__*100+__GNUC_MINOR__>301) ///
  12. # pragma GCC system_header ///
  13. # endif ///
  14. #endif ///
  15. #include <boost/leaf/detail/mp11.hpp>
  16. #include <tuple>
  17. namespace boost { namespace leaf {
  18. namespace leaf_detail
  19. {
  20. template<class...>
  21. struct gcc49_workaround //Thanks Glen Fernandes
  22. {
  23. using type = void;
  24. };
  25. template<class... T>
  26. using void_t = typename gcc49_workaround<T...>::type;
  27. template<class F,class V=void>
  28. struct function_traits
  29. {
  30. constexpr static int arity = -1;
  31. };
  32. template<class F>
  33. struct function_traits<F, void_t<decltype(&F::operator())>>
  34. {
  35. private:
  36. using tr = function_traits<decltype(&F::operator())>;
  37. public:
  38. using return_type = typename tr::return_type;
  39. static constexpr int arity = tr::arity - 1;
  40. using mp_args = typename leaf_detail_mp11::mp_rest<typename tr::mp_args>;
  41. template <int I>
  42. struct arg:
  43. tr::template arg<I+1>
  44. {
  45. };
  46. };
  47. template<class R, class... A>
  48. struct function_traits<R(A...)>
  49. {
  50. using return_type = R;
  51. static constexpr int arity = sizeof...(A);
  52. using mp_args = leaf_detail_mp11::mp_list<A...>;
  53. template <int I>
  54. struct arg
  55. {
  56. static_assert(I < arity, "I out of range");
  57. using type = typename std::tuple_element<I,std::tuple<A...>>::type;
  58. };
  59. };
  60. template<class F> struct function_traits<F&> : function_traits<F> { };
  61. template<class F> struct function_traits<F&&> : function_traits<F> { };
  62. template<class R, class... A> struct function_traits<R(*)(A...)> : function_traits<R(A...)> { };
  63. template<class R, class... A> struct function_traits<R(* &)(A...)> : function_traits<R(A...)> { };
  64. template<class R, class... A> struct function_traits<R(* const &)(A...)> : function_traits<R(A...)> { };
  65. template<class C, class R, class... A> struct function_traits<R(C::*)(A...)> : function_traits<R(C&,A...)> { };
  66. template<class C, class R, class... A> struct function_traits<R(C::*)(A...) const> : function_traits<R(C const &,A...)> { };
  67. template<class C, class R> struct function_traits<R(C::*)> : function_traits<R(C&)> { };
  68. template <class F>
  69. using fn_return_type = typename function_traits<F>::return_type;
  70. template <class F, int I>
  71. using fn_arg_type = typename function_traits<F>::template arg<I>::type;
  72. template <class F>
  73. using fn_mp_args = typename function_traits<F>::mp_args;
  74. }
  75. } }
  76. #if defined(_MSC_VER) && !defined(BOOST_LEAF_ENABLE_WARNINGS) ///
  77. #pragma warning(pop) ///
  78. #endif ///
  79. #endif