overload.hpp 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /*!
  2. @file
  3. Defines `boost::hana::overload`.
  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_OVERLOAD_HPP
  9. #define BOOST_HANA_FUNCTIONAL_OVERLOAD_HPP
  10. #include <boost/hana/config.hpp>
  11. #include <boost/hana/detail/decay.hpp>
  12. BOOST_HANA_NAMESPACE_BEGIN
  13. //! @ingroup group-functional
  14. //! Pick one of several functions to call based on overload resolution.
  15. //!
  16. //! Specifically, `overload(f1, f2, ..., fn)` is a function object such
  17. //! that
  18. //! @code
  19. //! overload(f1, f2, ..., fn)(x...) == fk(x...)
  20. //! @endcode
  21. //!
  22. //! where `fk` is the function of `f1, ..., fn` that would be called if
  23. //! overload resolution was performed amongst that set of functions only.
  24. //! If more than one function `fk` would be picked by overload resolution,
  25. //! then the call is ambiguous.
  26. //!
  27. //! ### Example
  28. //! @include example/functional/overload.cpp
  29. #ifdef BOOST_HANA_DOXYGEN_INVOKED
  30. constexpr auto overload = [](auto&& f1, auto&& f2, ..., auto&& fn) {
  31. return [perfect-capture](auto&& ...x) -> decltype(auto) {
  32. return forwarded(fk)(forwarded(x)...);
  33. };
  34. };
  35. #else
  36. template <typename F, typename ...G>
  37. struct overload_t
  38. : overload_t<F>::type
  39. , overload_t<G...>::type
  40. {
  41. using type = overload_t;
  42. using overload_t<F>::type::operator();
  43. using overload_t<G...>::type::operator();
  44. template <typename F_, typename ...G_>
  45. constexpr explicit overload_t(F_&& f, G_&& ...g)
  46. : overload_t<F>::type(static_cast<F_&&>(f))
  47. , overload_t<G...>::type(static_cast<G_&&>(g)...)
  48. { }
  49. };
  50. template <typename F>
  51. struct overload_t<F> { using type = F; };
  52. template <typename R, typename ...Args>
  53. struct overload_t<R(*)(Args...)> {
  54. using type = overload_t;
  55. R (*fptr_)(Args...);
  56. explicit constexpr overload_t(R (*fp)(Args...))
  57. : fptr_(fp)
  58. { }
  59. constexpr R operator()(Args ...args) const
  60. { return fptr_(static_cast<Args&&>(args)...); }
  61. };
  62. struct make_overload_t {
  63. template <typename ...F,
  64. typename Overload = typename overload_t<
  65. typename detail::decay<F>::type...
  66. >::type
  67. >
  68. constexpr Overload operator()(F&& ...f) const {
  69. return Overload(static_cast<F&&>(f)...);
  70. }
  71. };
  72. constexpr make_overload_t overload{};
  73. #endif
  74. BOOST_HANA_NAMESPACE_END
  75. #endif // !BOOST_HANA_FUNCTIONAL_OVERLOAD_HPP