1 /*=============================================================================
2 Copyright (c) 2017 Paul Fultz II
3 flow.cpp
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 #include <boost/hof/flow.hpp>
8 #include <boost/hof/function.hpp>
9 #include <boost/hof/lambda.hpp>
10 #include <boost/hof/placeholders.hpp>
11 #include <memory>
12 #include "test.hpp"
13
14 namespace flow_test {
15 struct increment
16 {
17 template<class T>
operator ()flow_test::increment18 constexpr T operator()(T x) const noexcept
19 {
20 return x + 1;
21 }
22 };
23
24 struct decrement
25 {
26 template<class T>
operator ()flow_test::decrement27 constexpr T operator()(T x) const noexcept
28 {
29 return x - 1;
30 }
31 };
32
33 struct negate
34 {
35 template<class T>
operator ()flow_test::negate36 constexpr T operator()(T x) const noexcept
37 {
38 return -x;
39 }
40 };
41
42 struct increment_movable
43 {
44 std::unique_ptr<int> n;
increment_movableflow_test::increment_movable45 increment_movable()
46 : n(new int(1))
47 {}
48 template<class T>
operator ()flow_test::increment_movable49 T operator()(T x) const
50 {
51 return x + *n;
52 }
53 };
54
55 struct decrement_movable
56 {
57 std::unique_ptr<int> n;
decrement_movableflow_test::decrement_movable58 decrement_movable()
59 : n(new int(1))
60 {}
61 template<class T>
operator ()flow_test::decrement_movable62 T operator()(T x) const
63 {
64 return x - *n;
65 }
66 };
67 #if BOOST_HOF_HAS_NOEXCEPT_DEDUCTION
BOOST_HOF_TEST_CASE()68 BOOST_HOF_TEST_CASE()
69 {
70 static_assert(noexcept(boost::hof::flow(increment(), decrement(), increment())(3)), "noexcept flow");
71 }
72 #endif
73
BOOST_HOF_TEST_CASE()74 BOOST_HOF_TEST_CASE()
75 {
76 BOOST_HOF_TEST_CHECK(boost::hof::flow(boost::hof::identity)(3) == 3);
77 BOOST_HOF_TEST_CHECK(boost::hof::flow(boost::hof::identity, boost::hof::identity)(3) == 3);
78 BOOST_HOF_TEST_CHECK(boost::hof::flow(boost::hof::identity, boost::hof::identity, boost::hof::identity)(3) == 3);
79
80 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::flow(boost::hof::identity)(3) == 3);
81 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::flow(boost::hof::identity, boost::hof::identity)(3) == 3);
82 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::flow(boost::hof::identity, boost::hof::identity, boost::hof::identity)(3) == 3);
83 }
84
BOOST_HOF_TEST_CASE()85 BOOST_HOF_TEST_CASE()
86 {
87 int r = boost::hof::flow(increment(), decrement(), increment())(3);
88 BOOST_HOF_TEST_CHECK(r == 4);
89 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::flow(increment(), decrement(), increment())(3) == 4);
90 }
91
BOOST_HOF_TEST_CASE()92 BOOST_HOF_TEST_CASE()
93 {
94 int r = boost::hof::flow(increment(), negate(), decrement(), decrement())(3);
95 BOOST_HOF_TEST_CHECK(r == -6);
96 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::flow(increment(), negate(), decrement(), decrement())(3) == -6);
97 }
98 #ifndef _MSC_VER
BOOST_HOF_TEST_CASE()99 BOOST_HOF_TEST_CASE()
100 {
101 constexpr auto f = boost::hof::flow(increment(), decrement());
102 static_assert(std::is_empty<decltype(f)>::value, "Compose function not empty");
103 int r = f(3);
104 BOOST_HOF_TEST_CHECK(r == 3);
105 BOOST_HOF_STATIC_TEST_CHECK(f(3) == 3);
106 }
107 #endif
108
BOOST_HOF_TEST_CASE()109 BOOST_HOF_TEST_CASE()
110 {
111 STATIC_ASSERT_MOVE_ONLY(increment_movable);
112 STATIC_ASSERT_MOVE_ONLY(decrement_movable);
113 int r = boost::hof::flow(increment_movable(), decrement_movable(), increment_movable())(3);
114 BOOST_HOF_TEST_CHECK(r == 4);
115 }
116
BOOST_HOF_TEST_CASE()117 BOOST_HOF_TEST_CASE()
118 {
119 const auto f = boost::hof::flow([](int i) { return i+1; }, [](int i) { return i-1; }, [](int i) { return i+1; });
120 #ifndef _MSC_VER
121 static_assert(std::is_empty<decltype(f)>::value, "Compose function not empty");
122 #endif
123 int r = f(3);
124 BOOST_HOF_TEST_CHECK(r == 4);
125 }
126
127
128 BOOST_HOF_STATIC_FUNCTION(f_flow_single_function) = boost::hof::flow(increment());
129
BOOST_HOF_TEST_CASE()130 BOOST_HOF_TEST_CASE()
131 {
132 BOOST_HOF_TEST_CHECK(f_flow_single_function(3) == 4);
133 BOOST_HOF_STATIC_TEST_CHECK(f_flow_single_function(3) == 4);
134 }
135
136 BOOST_HOF_STATIC_FUNCTION(f_flow_function) = boost::hof::flow(increment(), decrement(), increment());
137
BOOST_HOF_TEST_CASE()138 BOOST_HOF_TEST_CASE()
139 {
140 BOOST_HOF_TEST_CHECK(f_flow_function(3) == 4);
141 BOOST_HOF_STATIC_TEST_CHECK(f_flow_function(3) == 4);
142 }
143
144 BOOST_HOF_STATIC_FUNCTION(f_flow_function_4) = boost::hof::flow(increment(), negate(), decrement(), decrement());
145
BOOST_HOF_TEST_CASE()146 BOOST_HOF_TEST_CASE()
147 {
148 BOOST_HOF_TEST_CHECK(f_flow_function_4(3) == -6);
149 BOOST_HOF_STATIC_TEST_CHECK(f_flow_function_4(3) == -6);
150 }
151
152 BOOST_HOF_STATIC_LAMBDA_FUNCTION(f_flow_lambda) = boost::hof::flow(
__anon0eaf7d350402(int i) 153 [](int i) { return i+1; },
__anon0eaf7d350502(int i) 154 [](int i) { return i-1; },
__anon0eaf7d350602(int i) 155 [](int i) { return i+1; }
156 );
157
BOOST_HOF_TEST_CASE()158 BOOST_HOF_TEST_CASE()
159 {
160 int r = f_flow_lambda(3);
161 BOOST_HOF_TEST_CHECK(r == 4);
162 }
163
BOOST_HOF_TEST_CASE()164 BOOST_HOF_TEST_CASE()
165 {
166 BOOST_HOF_TEST_CHECK(boost::hof::flow(boost::hof::_1 + boost::hof::_1, boost::hof::_1 * boost::hof::_1)(3) == 36);
167 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::flow(boost::hof::_1 + boost::hof::_1, boost::hof::_1 * boost::hof::_1)(3) == 36);
168 }
169 }
170