1 /*=============================================================================
2     Copyright (c) 2015 Paul Fultz II
3     flip.h
4     Distributed under the Boost Software License, Version 1.0. (See accompanying
5     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 ==============================================================================*/
7 
8 #ifndef BOOST_HOF_GUARD_FLIP_H
9 #define BOOST_HOF_GUARD_FLIP_H
10 
11 /// flip
12 /// ====
13 ///
14 /// Description
15 /// -----------
16 ///
17 /// The `flip` function adaptor swaps the first two parameters.
18 ///
19 /// Synopsis
20 /// --------
21 ///
22 ///     template<class F>
23 ///     flip_adaptor<F> flip(F f);
24 ///
25 /// Semantics
26 /// ---------
27 ///
28 ///     assert(flip(f)(x, y, xs...) == f(y, x, xs...));
29 ///
30 /// Requirements
31 /// ------------
32 ///
33 /// F must be at least:
34 ///
35 /// * [BinaryInvocable](BinaryInvocable)
36 ///
37 /// Or:
38 ///
39 /// * [Invocable](Invocable) with more than two argurments
40 ///
41 /// And:
42 ///
43 /// * MoveConstructible
44 ///
45 /// Example
46 /// -------
47 ///
48 ///     #include <boost/hof.hpp>
49 ///     #include <cassert>
50 ///
51 ///     int main() {
52 ///         int r = boost::hof::flip(boost::hof::_ - boost::hof::_)(2, 5);
53 ///         assert(r == 3);
54 ///     }
55 ///
56 
57 #include <boost/hof/detail/callable_base.hpp>
58 #include <boost/hof/reveal.hpp>
59 #include <boost/hof/detail/make.hpp>
60 #include <boost/hof/detail/static_const_var.hpp>
61 
62 namespace boost { namespace hof {
63 
64 template<class F>
65 struct flip_adaptor : detail::callable_base<F>
66 {
67     typedef flip_adaptor fit_rewritable1_tag;
68     BOOST_HOF_INHERIT_CONSTRUCTOR(flip_adaptor, detail::callable_base<F>);
69 
70     template<class... Ts>
base_functionboost::hof::flip_adaptor71     constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
72     {
73         return boost::hof::always_ref(*this)(xs...);
74     }
75 
76     struct flip_failure
77     {
78         template<class Failure>
79         struct apply
80         {
81             template<class T, class U, class... Ts>
82             struct of
83             : Failure::template of<U, T, Ts...>
84             {};
85         };
86     };
87 
88     struct failure
89     : failure_map<flip_failure, detail::callable_base<F>>
90     {};
91 
92     BOOST_HOF_RETURNS_CLASS(flip_adaptor);
93 
94     template<class T, class U, class... Ts>
95     constexpr BOOST_HOF_SFINAE_RESULT(const detail::callable_base<F>&, id_<U>, id_<T>, id_<Ts>...)
96     operator()(T&& x, U&& y, Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
97     (
98         (BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(xs...)))
99             (BOOST_HOF_FORWARD(U)(y), BOOST_HOF_FORWARD(T)(x), BOOST_HOF_FORWARD(Ts)(xs)...)
100     );
101 };
102 
103 BOOST_HOF_DECLARE_STATIC_VAR(flip, detail::make<flip_adaptor>);
104 
105 }} // namespace boost::hof
106 
107 #endif
108