mem_fn.hpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #ifndef BOOST_COMPAT_MEM_FN_HPP_INCLUDED
  2. #define BOOST_COMPAT_MEM_FN_HPP_INCLUDED
  3. // Copyright 2024 Peter Dimov
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // https://www.boost.org/LICENSE_1_0.txt
  6. #include <boost/compat/type_traits.hpp>
  7. #include <boost/compat/detail/returns.hpp>
  8. #include <functional>
  9. namespace boost {
  10. namespace compat {
  11. namespace detail {
  12. template<class T, class U, class Td = remove_cvref_t<T>, class Ud = remove_cvref_t<U>>
  13. struct is_same_or_base: std::integral_constant<bool, std::is_same<Td, Ud>::value || std::is_base_of<Td, Ud>::value>
  14. {
  15. };
  16. template<class T> struct is_reference_wrapper_: std::false_type {};
  17. template<class T> struct is_reference_wrapper_< std::reference_wrapper<T> >: std::true_type {};
  18. template<class T> struct is_reference_wrapper: is_reference_wrapper_< remove_cvref_t<T> > {};
  19. template<class M, class T> struct _mfn
  20. {
  21. M T::* pm_;
  22. template<class U, class... A, class En = enable_if_t<is_same_or_base<T, U>::value>>
  23. constexpr auto operator()( U&& u, A&&... a ) const
  24. BOOST_COMPAT_RETURNS( (std::forward<U>(u).*pm_)( std::forward<A>(a)... ) )
  25. template<class U, class... A, class = void, class En = enable_if_t< !is_same_or_base<T, U>::value && is_reference_wrapper<U>::value>>
  26. constexpr auto operator()( U&& u, A&&... a ) const
  27. BOOST_COMPAT_RETURNS( (u.get().*pm_)( std::forward<A>(a)... ) )
  28. template<class U, class... A, class = void, class = void, class En = enable_if_t< !is_same_or_base<T, U>::value && !is_reference_wrapper<U>::value>>
  29. constexpr auto operator()( U&& u, A&&... a ) const
  30. BOOST_COMPAT_RETURNS( ((*std::forward<U>(u)).*pm_)( std::forward<A>(a)... ) )
  31. };
  32. template<class M, class T> struct _md
  33. {
  34. M T::* pm_;
  35. template<class U, class En = enable_if_t<is_same_or_base<T, U>::value>>
  36. constexpr auto operator()( U&& u ) const
  37. BOOST_COMPAT_RETURNS( std::forward<U>(u).*pm_ )
  38. template<class U, class = void, class En = enable_if_t< !is_same_or_base<T, U>::value && is_reference_wrapper<U>::value>>
  39. constexpr auto operator()( U&& u ) const
  40. BOOST_COMPAT_RETURNS( u.get().*pm_ )
  41. template<class U, class = void, class = void, class En = enable_if_t< !is_same_or_base<T, U>::value && !is_reference_wrapper<U>::value>>
  42. constexpr auto operator()( U&& u ) const
  43. BOOST_COMPAT_RETURNS( (*std::forward<U>(u)).*pm_ )
  44. };
  45. } // namespace detail
  46. template<class M, class T, class En = enable_if_t< std::is_function<M>::value > >
  47. constexpr auto mem_fn( M T::* pm ) noexcept -> detail::_mfn<M, T>
  48. {
  49. return detail::_mfn<M, T>{ pm };
  50. }
  51. template<class M, class T, class = void, class En = enable_if_t< !std::is_function<M>::value > >
  52. constexpr auto mem_fn( M T::* pm ) noexcept -> detail::_md<M, T>
  53. {
  54. return detail::_md<M, T>{ pm };
  55. }
  56. } // namespace compat
  57. } // namespace boost
  58. #endif // BOOST_COMPAT_MEM_FN_HPP_INCLUDED