invoke.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #ifndef BOOST_COMPAT_INVOKE_HPP_INCLUDED
  2. #define BOOST_COMPAT_INVOKE_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/mem_fn.hpp>
  7. #include <boost/compat/type_traits.hpp>
  8. #include <boost/compat/detail/returns.hpp>
  9. #include <boost/config.hpp>
  10. #include <boost/config/workaround.hpp>
  11. #include <utility>
  12. namespace boost {
  13. namespace compat {
  14. // invoke
  15. template<class F, class... A>
  16. constexpr auto invoke( F&& f, A&&... a )
  17. BOOST_COMPAT_RETURNS( std::forward<F>(f)(std::forward<A>(a)...) )
  18. template<class M, class T, class... A>
  19. constexpr auto invoke( M T::* pm, A&&... a )
  20. BOOST_COMPAT_RETURNS( compat::mem_fn(pm)(std::forward<A>(a)...) )
  21. // invoke_result_t
  22. template<class F, class... A> using invoke_result_t = decltype( compat::invoke( std::declval<F>(), std::declval<A>()... ) );
  23. // is_invocable
  24. namespace detail {
  25. template<class, class F, class... A> struct is_invocable_: std::false_type {};
  26. template<class F, class... A> struct is_invocable_< void_t<invoke_result_t<F, A...>>, F, A... >: std::true_type {};
  27. } // namespace detail
  28. template<class F, class... A> struct is_invocable: detail::is_invocable_<void, F, A...> {};
  29. // is_nothrow_invocable
  30. #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
  31. template<class F, class... A> struct is_nothrow_invocable: std::false_type {};
  32. #else
  33. namespace detail {
  34. template<class F, class... A> struct is_nothrow_invocable_
  35. {
  36. using type = std::integral_constant<bool, noexcept( compat::invoke( std::declval<F>(), std::declval<A>()... ) )>;
  37. };
  38. } // namespace detail
  39. template<class F, class... A> struct is_nothrow_invocable: conditional_t< is_invocable<F, A...>::value, detail::is_nothrow_invocable_<F, A...>, std::false_type >::type {};
  40. #endif
  41. // invoke_r
  42. template<class R, class F, class... A, class En = enable_if_t<
  43. std::is_void<R>::value && is_invocable<F, A...>::value >>
  44. constexpr R invoke_r( F&& f, A&&... a )
  45. noexcept( noexcept( static_cast<R>( compat::invoke( std::forward<F>(f), std::forward<A>(a)... ) ) ) )
  46. {
  47. return static_cast<R>( compat::invoke( std::forward<F>(f), std::forward<A>(a)... ) );
  48. }
  49. template<class R, class F, class... A, class = void, class En = enable_if_t<
  50. !std::is_void<R>::value && std::is_convertible< invoke_result_t<F, A...>, R >::value >>
  51. constexpr R invoke_r( F&& f, A&&... a )
  52. noexcept( noexcept( static_cast<R>( compat::invoke( std::forward<F>(f), std::forward<A>(a)... ) ) ) )
  53. {
  54. return compat::invoke( std::forward<F>(f), std::forward<A>(a)... );
  55. }
  56. // is_invocable_r
  57. namespace detail {
  58. template<class R, class F, class... A> struct is_invocable_r_: std::is_convertible< invoke_result_t<F, A...>, R > {};
  59. } // namespace detail
  60. template<class R, class F, class... A> struct is_invocable_r:
  61. conditional_t< !is_invocable<F, A...>::value, std::false_type,
  62. conditional_t< std::is_void<R>::value, std::true_type,
  63. detail::is_invocable_r_<R, F, A...> >> {};
  64. // is_nothrow_invocable_r
  65. #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
  66. template<class R, class F, class... A> struct is_nothrow_invocable_r: std::false_type {};
  67. #else
  68. namespace detail {
  69. template<class R, class F, class... A> struct is_nothrow_invocable_r_
  70. {
  71. using type = std::integral_constant<bool, noexcept( compat::invoke_r<R>( std::declval<F>(), std::declval<A>()... ) )>;
  72. };
  73. } // namespace detail
  74. template<class R, class F, class... A> struct is_nothrow_invocable_r: conditional_t< is_invocable_r<R, F, A...>::value, detail::is_nothrow_invocable_r_<R, F, A...>, std::false_type >::type {};
  75. #endif
  76. } // namespace compat
  77. } // namespace boost
  78. #endif // BOOST_COMPAT_INVOKE_HPP_INCLUDED