1 /*!
2 @file
3 Defines `boost::hana::overload`.
4 
5 @copyright Louis Dionne 2013-2017
6 Distributed under the Boost Software License, Version 1.0.
7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
8  */
9 
10 #ifndef BOOST_HANA_FUNCTIONAL_OVERLOAD_HPP
11 #define BOOST_HANA_FUNCTIONAL_OVERLOAD_HPP
12 
13 #include <boost/hana/config.hpp>
14 #include <boost/hana/detail/decay.hpp>
15 
16 
17 BOOST_HANA_NAMESPACE_BEGIN
18     //! @ingroup group-functional
19     //! Pick one of several functions to call based on overload resolution.
20     //!
21     //! Specifically, `overload(f1, f2, ..., fn)` is a function object such
22     //! that
23     //! @code
24     //!     overload(f1, f2, ..., fn)(x...) == fk(x...)
25     //! @endcode
26     //!
27     //! where `fk` is the function of `f1, ..., fn` that would be called if
28     //! overload resolution was performed amongst that set of functions only.
29     //! If more than one function `fk` would be picked by overload resolution,
30     //! then the call is ambiguous.
31     //!
32     //! ### Example
33     //! @include example/functional/overload.cpp
34 #ifdef BOOST_HANA_DOXYGEN_INVOKED
__anon958c37230102(auto&& f1, auto&& f2, ..., auto&& fn) 35     constexpr auto overload = [](auto&& f1, auto&& f2, ..., auto&& fn) {
36         return [perfect-capture](auto&& ...x) -> decltype(auto) {
37             return forwarded(fk)(forwarded(x)...);
38         };
39     };
40 #else
41     template <typename F, typename ...G>
42     struct overload_t
43         : overload_t<F>::type
44         , overload_t<G...>::type
45     {
46         using type = overload_t;
47         using overload_t<F>::type::operator();
48         using overload_t<G...>::type::operator();
49 
50         template <typename F_, typename ...G_>
51         constexpr explicit overload_t(F_&& f, G_&& ...g)
52             : overload_t<F>::type(static_cast<F_&&>(f))
53             , overload_t<G...>::type(static_cast<G_&&>(g)...)
54         { }
55     };
56 
57     template <typename F>
58     struct overload_t<F> { using type = F; };
59 
60     template <typename R, typename ...Args>
61     struct overload_t<R(*)(Args...)> {
62         using type = overload_t;
63         R (*fptr_)(Args...);
64 
65         explicit constexpr overload_t(R (*fp)(Args...))
66             : fptr_(fp)
67         { }
68 
69         constexpr R operator()(Args ...args) const
70         { return fptr_(static_cast<Args&&>(args)...); }
71     };
72 
73     struct make_overload_t {
74         template <typename ...F,
75             typename Overload = typename overload_t<
76                 typename detail::decay<F>::type...
77             >::type
78         >
79         constexpr Overload operator()(F&& ...f) const {
80             return Overload(static_cast<F&&>(f)...);
81         }
82     };
83 
84     constexpr make_overload_t overload{};
85 #endif
86 BOOST_HANA_NAMESPACE_END
87 
88 #endif // !BOOST_HANA_FUNCTIONAL_OVERLOAD_HPP
89