1 /*=============================================================================
2 Copyright (c) 2017 Paul Fultz II
3 compose.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/compose.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 compose_test {
15 struct increment
16 {
17 template<class T>
operator ()compose_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 ()compose_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 ()compose_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_movablecompose_test::increment_movable45 increment_movable()
46 : n(new int(1))
47 {}
48 template<class T>
operator ()compose_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_movablecompose_test::decrement_movable58 decrement_movable()
59 : n(new int(1))
60 {}
61 template<class T>
operator ()compose_test::decrement_movable62 T operator()(T x) const
63 {
64 return x - *n;
65 }
66 };
67
68 #if BOOST_HOF_HAS_NOEXCEPT_DEDUCTION
BOOST_HOF_TEST_CASE()69 BOOST_HOF_TEST_CASE()
70 {
71 static_assert(noexcept(boost::hof::compose(increment(), decrement(), increment())(3)), "noexcept compose");
72 }
73 #endif
74
BOOST_HOF_TEST_CASE()75 BOOST_HOF_TEST_CASE()
76 {
77 BOOST_HOF_TEST_CHECK(boost::hof::compose(boost::hof::identity)(3) == 3);
78 BOOST_HOF_TEST_CHECK(boost::hof::compose(boost::hof::identity, boost::hof::identity)(3) == 3);
79 BOOST_HOF_TEST_CHECK(boost::hof::compose(boost::hof::identity, boost::hof::identity, boost::hof::identity)(3) == 3);
80
81 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::compose(boost::hof::identity)(3) == 3);
82 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::compose(boost::hof::identity, boost::hof::identity)(3) == 3);
83 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::compose(boost::hof::identity, boost::hof::identity, boost::hof::identity)(3) == 3);
84 }
85
BOOST_HOF_TEST_CASE()86 BOOST_HOF_TEST_CASE()
87 {
88 int r = boost::hof::compose(increment(), decrement(), increment())(3);
89 BOOST_HOF_TEST_CHECK(r == 4);
90 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::compose(increment(), decrement(), increment())(3) == 4);
91 }
92
BOOST_HOF_TEST_CASE()93 BOOST_HOF_TEST_CASE()
94 {
95 int r = boost::hof::compose(increment(), negate(), decrement(), decrement())(3);
96 BOOST_HOF_TEST_CHECK(r == 0);
97 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::compose(increment(), negate(), decrement(), decrement())(3) == 0);
98 }
BOOST_HOF_TEST_CASE()99 BOOST_HOF_TEST_CASE()
100 {
101 constexpr auto f = boost::hof::compose(increment(), decrement());
102 #ifndef _MSC_VER
103 static_assert(std::is_empty<decltype(f)>::value, "Compose function not empty");
104 #endif
105 static_assert(BOOST_HOF_IS_DEFAULT_CONSTRUCTIBLE(decltype(f)), "Compose function not default constructible");
106 int r = f(3);
107 BOOST_HOF_TEST_CHECK(r == 3);
108 BOOST_HOF_STATIC_TEST_CHECK(f(3) == 3);
109 }
110
111 #ifndef _MSC_VER
BOOST_HOF_TEST_CASE()112 BOOST_HOF_TEST_CASE()
113 {
114 constexpr auto f = boost::hof::compose(increment(), negate(), decrement(), decrement());
115 static_assert(std::is_empty<decltype(f)>::value, "Compose function not empty");
116 static_assert(BOOST_HOF_IS_DEFAULT_CONSTRUCTIBLE(decltype(f)), "Compose function not default constructible");
117 int r = f(3);
118 BOOST_HOF_TEST_CHECK(r == 0);
119 BOOST_HOF_STATIC_TEST_CHECK(f(3) == 0);
120 }
121 #endif
122
BOOST_HOF_TEST_CASE()123 BOOST_HOF_TEST_CASE()
124 {
125 STATIC_ASSERT_MOVE_ONLY(increment_movable);
126 STATIC_ASSERT_MOVE_ONLY(decrement_movable);
127 int r = boost::hof::compose(increment_movable(), decrement_movable(), increment_movable())(3);
128 BOOST_HOF_TEST_CHECK(r == 4);
129 }
130
131 template<class T>
132 struct print;
133
BOOST_HOF_TEST_CASE()134 BOOST_HOF_TEST_CASE()
135 {
136 const auto f = boost::hof::compose([](int i) { return i+1; }, [](int i) { return i-1; }, [](int i) { return i+1; });
137 #ifndef _MSC_VER
138 static_assert(std::is_empty<decltype(f)>::value, "Compose function not empty");
139 #endif
140 int r = f(3);
141 BOOST_HOF_TEST_CHECK(r == 4);
142 }
143
144
145 BOOST_HOF_STATIC_FUNCTION(f_compose_single_function) = boost::hof::compose(increment());
146
BOOST_HOF_TEST_CASE()147 BOOST_HOF_TEST_CASE()
148 {
149 BOOST_HOF_TEST_CHECK(f_compose_single_function(3) == 4);
150 BOOST_HOF_STATIC_TEST_CHECK(f_compose_single_function(3) == 4);
151 }
152
153 BOOST_HOF_STATIC_FUNCTION(f_compose_function) = boost::hof::compose(increment(), decrement(), increment());
154
BOOST_HOF_TEST_CASE()155 BOOST_HOF_TEST_CASE()
156 {
157 BOOST_HOF_TEST_CHECK(f_compose_function(3) == 4);
158 BOOST_HOF_STATIC_TEST_CHECK(f_compose_function(3) == 4);
159 }
160
161 BOOST_HOF_STATIC_FUNCTION(f_compose_function_4) = boost::hof::compose(increment(), negate(), decrement(), decrement());
162
BOOST_HOF_TEST_CASE()163 BOOST_HOF_TEST_CASE()
164 {
165 BOOST_HOF_TEST_CHECK(f_compose_function_4(3) == 0);
166 BOOST_HOF_STATIC_TEST_CHECK(f_compose_function_4(3) == 0);
167 }
168
169 BOOST_HOF_STATIC_LAMBDA_FUNCTION(f_compose_lambda) = boost::hof::compose(
__anon562db9130402(int i) 170 [](int i) { return i+1; },
__anon562db9130502(int i) 171 [](int i) { return i-1; },
__anon562db9130602(int i) 172 [](int i) { return i+1; }
173 );
174
BOOST_HOF_TEST_CASE()175 BOOST_HOF_TEST_CASE()
176 {
177 int r = f_compose_lambda(3);
178 BOOST_HOF_TEST_CHECK(r == 4);
179 }
180
BOOST_HOF_TEST_CASE()181 BOOST_HOF_TEST_CASE()
182 {
183 BOOST_HOF_TEST_CHECK(boost::hof::compose(boost::hof::_1 * boost::hof::_1, boost::hof::_1 + boost::hof::_1)(3) == 36);
184 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::compose(boost::hof::_1 * boost::hof::_1, boost::hof::_1 + boost::hof::_1)(3) == 36);
185 }
186 }
187