apply.hpp 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*!
  2. @file
  3. Defines `boost::hana::apply`.
  4. @copyright Louis Dionne 2013-2017
  5. Distributed under the Boost Software License, Version 1.0.
  6. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  7. */
  8. #ifndef BOOST_HANA_FUNCTIONAL_APPLY_HPP
  9. #define BOOST_HANA_FUNCTIONAL_APPLY_HPP
  10. #include <boost/hana/config.hpp>
  11. BOOST_HANA_NAMESPACE_BEGIN
  12. //! @ingroup group-functional
  13. //! Invokes a Callable with the given arguments.
  14. //!
  15. //! This is equivalent to [std::invoke][1] that will be added in C++17.
  16. //! However, `apply` is a function object instead of a function, which
  17. //! makes it possible to pass it to higher-order algorithms.
  18. //!
  19. //!
  20. //! @param f
  21. //! A [Callable][2] to be invoked with the given arguments.
  22. //!
  23. //! @param x...
  24. //! The arguments to call `f` with. The number of `x...` must match the
  25. //! arity of `f`.
  26. //!
  27. //!
  28. //! Example
  29. //! -------
  30. //! @include example/functional/apply.cpp
  31. //!
  32. //! [1]: http://en.cppreference.com/w/cpp/utility/functional/invoke
  33. //! [2]: http://en.cppreference.com/w/cpp/named_req/Callable
  34. #ifdef BOOST_HANA_DOXYGEN_INVOKED
  35. constexpr auto apply = [](auto&& f, auto&& ...x) -> decltype(auto) {
  36. return forwarded(f)(forwarded(x)...);
  37. };
  38. #else
  39. struct apply_t {
  40. template <typename F, typename... Args>
  41. constexpr auto operator()(F&& f, Args&&... args) const ->
  42. decltype(static_cast<F&&>(f)(static_cast<Args&&>(args)...))
  43. {
  44. return static_cast<F&&>(f)(static_cast<Args&&>(args)...);
  45. }
  46. template <typename Base, typename T, typename Derived>
  47. constexpr auto operator()(T Base::*pmd, Derived&& ref) const ->
  48. decltype(static_cast<Derived&&>(ref).*pmd)
  49. {
  50. return static_cast<Derived&&>(ref).*pmd;
  51. }
  52. template <typename PMD, typename Pointer>
  53. constexpr auto operator()(PMD pmd, Pointer&& ptr) const ->
  54. decltype((*static_cast<Pointer&&>(ptr)).*pmd)
  55. {
  56. return (*static_cast<Pointer&&>(ptr)).*pmd;
  57. }
  58. template <typename Base, typename T, typename Derived, typename... Args>
  59. constexpr auto operator()(T Base::*pmf, Derived&& ref, Args&&... args) const ->
  60. decltype((static_cast<Derived&&>(ref).*pmf)(static_cast<Args&&>(args)...))
  61. {
  62. return (static_cast<Derived&&>(ref).*pmf)(static_cast<Args&&>(args)...);
  63. }
  64. template <typename PMF, typename Pointer, typename... Args>
  65. constexpr auto operator()(PMF pmf, Pointer&& ptr, Args&& ...args) const ->
  66. decltype(((*static_cast<Pointer&&>(ptr)).*pmf)(static_cast<Args&&>(args)...))
  67. {
  68. return ((*static_cast<Pointer&&>(ptr)).*pmf)(static_cast<Args&&>(args)...);
  69. }
  70. };
  71. constexpr apply_t apply{};
  72. #endif
  73. BOOST_HANA_NAMESPACE_END
  74. #endif // !BOOST_HANA_FUNCTIONAL_APPLY_HPP