1 /*=============================================================================
2 Copyright (c) 2017 Paul Fultz II
3 tuple_for_each.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/unpack.hpp>
8 #include <boost/hof/proj.hpp>
9 #include <boost/hof/function.hpp>
10 #include <boost/hof/reveal.hpp>
11 #include "test.hpp"
12
13 struct tuple_for_each_f
14 {
15 template<class Sequence, class F>
16 constexpr auto operator()(Sequence&& s, F && f) const BOOST_HOF_RETURNS
17 (
18 boost::hof::unpack(boost::hof::proj(boost::hof::forward<F>(f)))(boost::hof::forward<Sequence>(s)), boost::hof::forward<F>(f)
19 );
20 };
21
BOOST_HOF_STATIC_FUNCTION(tuple_for_each)22 BOOST_HOF_STATIC_FUNCTION(tuple_for_each) = tuple_for_each_f{};
23
BOOST_HOF_TEST_CASE()24 BOOST_HOF_TEST_CASE()
25 {
26 std::tuple<int, short, char> tp{ 1, 2, 3 };
27
28 {
29 int s = 0;
30
31 tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } );
32
33 BOOST_HOF_TEST_CHECK( s == 123 );
34 }
35
36 {
37 int s = 0;
38
39 tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } );
40
41 BOOST_HOF_TEST_CHECK( s == 123 );
42 }
43 }
BOOST_HOF_TEST_CASE()44 BOOST_HOF_TEST_CASE()
45 {
46 std::tuple<int, short, char> const tp{ 1, 2, 3 };
47
48 {
49 int s = 0;
50
51 tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } );
52
53 BOOST_HOF_TEST_CHECK( s == 123 );
54 }
55
56 {
57 int s = 0;
58
59 tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } );
60
61 BOOST_HOF_TEST_CHECK( s == 123 );
62 }
63 }
64
65 // #if defined( __clang_major__ ) && __clang_major__ == 3 && __clang_minor__ < 8
66 // #else
BOOST_HOF_TEST_CASE()67 BOOST_HOF_TEST_CASE()
68 {
69 std::tuple<std::unique_ptr<int>, std::unique_ptr<int>, std::unique_ptr<int>> tp{ std::unique_ptr<int>(new int(1)), std::unique_ptr<int>(new int(2)), std::unique_ptr<int>(new int(3)) };
70
71 int s = 0;
72
73 tuple_for_each( std::move(tp), [&]( std::unique_ptr<int> p ){ s = s * 10 + *p; } );
74
75 BOOST_HOF_TEST_CHECK( s == 123 );
76 }
77
BOOST_HOF_TEST_CASE()78 BOOST_HOF_TEST_CASE()
79 {
80 auto tp = boost::hof::pack(1, 2, 3);
81
82 {
83 int s = 0;
84
85 tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } );
86
87 BOOST_HOF_TEST_CHECK( s == 123 );
88 }
89
90 {
91 int s = 0;
92
93 tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } );
94
95 BOOST_HOF_TEST_CHECK( s == 123 );
96 }
97 }
BOOST_HOF_TEST_CASE()98 BOOST_HOF_TEST_CASE()
99 {
100 const auto tp = boost::hof::pack(1, 2, 3);
101
102 {
103 int s = 0;
104
105 tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } );
106
107 BOOST_HOF_TEST_CHECK( s == 123 );
108 }
109
110 {
111 int s = 0;
112
113 tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } );
114
115 BOOST_HOF_TEST_CHECK( s == 123 );
116 }
117 }
118 // #endif
BOOST_HOF_TEST_CASE()119 BOOST_HOF_TEST_CASE()
120 {
121 std::pair<int, short> tp{ 1, 2 };
122
123 {
124 int s = 0;
125
126 tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } );
127
128 BOOST_HOF_TEST_CHECK( s == 12 );
129 }
130
131 {
132 int s = 0;
133
134 tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } );
135
136 BOOST_HOF_TEST_CHECK( s == 12 );
137 }
138 }
BOOST_HOF_TEST_CASE()139 BOOST_HOF_TEST_CASE()
140 {
141 std::pair<int, short> const tp{ 1, 2 };
142
143 {
144 int s = 0;
145
146 tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } );
147
148 BOOST_HOF_TEST_CHECK( s == 12 );
149 }
150
151 {
152 int s = 0;
153
154 tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } );
155
156 BOOST_HOF_TEST_CHECK( s == 12 );
157 }
158 }
BOOST_HOF_TEST_CASE()159 BOOST_HOF_TEST_CASE()
160 {
161 std::array<int, 3> tp{{ 1, 2, 3 }};
162
163 {
164 int s = 0;
165
166 tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } );
167
168 BOOST_HOF_TEST_CHECK( s == 123 );
169 }
170
171 {
172 int s = 0;
173
174 tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } );
175
176 BOOST_HOF_TEST_CHECK( s == 123 );
177 }
178 }
BOOST_HOF_TEST_CASE()179 BOOST_HOF_TEST_CASE()
180 {
181 std::array<int, 3> const tp{{ 1, 2, 3 }};
182
183 {
184 int s = 0;
185
186 tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } );
187
188 BOOST_HOF_TEST_CHECK( s == 123 );
189 }
190
191 {
192 int s = 0;
193
194 tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } );
195
196 BOOST_HOF_TEST_CHECK( s == 123 );
197 }
198 }
BOOST_HOF_TEST_CASE()199 BOOST_HOF_TEST_CASE()
200 {
201 std::tuple<> tp;
202
203 BOOST_HOF_TEST_CHECK( tuple_for_each( tp, 11 ) == 11 );
204 BOOST_HOF_TEST_CHECK( tuple_for_each( std::move( tp ), 12 ) == 12 );
205 }
206
BOOST_HOF_TEST_CASE()207 BOOST_HOF_TEST_CASE()
208 {
209 BOOST_HOF_TEST_CHECK( tuple_for_each( boost::hof::pack(), 11 ) == 11 );
210 BOOST_HOF_STATIC_TEST_CHECK( tuple_for_each( boost::hof::pack(), 11 ) == 11 );
211 }
BOOST_HOF_TEST_CASE()212 BOOST_HOF_TEST_CASE()
213 {
214 std::array<int, 0> tp;
215
216 BOOST_HOF_TEST_CHECK( tuple_for_each( tp, 11 ) == 11 );
217 BOOST_HOF_TEST_CHECK( tuple_for_each( std::move( tp ), 12 ) == 12 );
218 }
219
220 struct assert_is_integral
221 {
operator ()assert_is_integral222 template<class T> constexpr bool operator()( T ) const
223 {
224 BOOST_HOF_STATIC_TEST_CHECK( std::is_integral<T>::value );
225 return true;
226 }
227 };
228
BOOST_HOF_TEST_CASE()229 BOOST_HOF_TEST_CASE()
230 {
231 #if !BOOST_HOF_HAS_CONSTEXPR_TUPLE
232 auto r = tuple_for_each( std::tuple<int, short, char>{1, 2, 3}, assert_is_integral() );
233 #else
234 constexpr auto r = tuple_for_each( std::tuple<int, short, char>{1, 2, 3}, assert_is_integral() );
235 #endif
236 (void)r;
237 }
238
BOOST_HOF_TEST_CASE()239 BOOST_HOF_TEST_CASE()
240 {
241 #if !BOOST_HOF_HAS_CONSTEXPR_TUPLE
242 auto r = tuple_for_each( boost::hof::pack(1, 2, 3), assert_is_integral() );
243 #else
244 constexpr auto r = tuple_for_each( boost::hof::pack(1, 2, 3), assert_is_integral() );
245 #endif
246 (void)r;
247 }
248