1/*=============================================================================
2 Copyright (c) 2017 Paul Fultz II
3 unpack.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/static.hpp>
9#include <boost/hof/lambda.hpp>
10#include "test.hpp"
11
12#include <memory>
13
14static constexpr boost::hof::static_<boost::hof::unpack_adaptor<unary_class> > unary_unpack = {};
15static constexpr boost::hof::static_<boost::hof::unpack_adaptor<binary_class> > binary_unpack = {};
16
17BOOST_HOF_STATIC_AUTO unary_unpack_constexpr = boost::hof::unpack_adaptor<unary_class>();
18#if BOOST_HOF_HAS_CONSTEXPR_TUPLE
19BOOST_HOF_STATIC_AUTO binary_unpack_constexpr = boost::hof::unpack_adaptor<binary_class>();
20#endif
21
22BOOST_HOF_STATIC_AUTO unary_unpack_reveal = boost::hof::reveal_adaptor<boost::hof::unpack_adaptor<unary_class>>();
23BOOST_HOF_STATIC_AUTO binary_unpack_reveal = boost::hof::reveal_adaptor<boost::hof::unpack_adaptor<binary_class>>();
24
25#if BOOST_HOF_HAS_NOEXCEPT_DEDUCTION
26BOOST_HOF_TEST_CASE()
27{
28 static_assert(noexcept(boost::hof::unpack(unary_class())(boost::hof::pack(3))), "noexcept unpack");
29 static_assert(noexcept(unary_unpack(boost::hof::pack(3))), "noexcept unpack");
30 static_assert(noexcept(binary_unpack(boost::hof::pack(3), boost::hof::pack(2))), "noexcept unpack");
31}
32#endif
33
34BOOST_HOF_TEST_CASE()
35{
36 BOOST_HOF_TEST_CHECK(3 == boost::hof::unpack(unary_class())(std::make_tuple(3)));
37 BOOST_HOF_TEST_CHECK(3 == unary_unpack(std::make_tuple(3)));
38 BOOST_HOF_TEST_CHECK(3 == unary_unpack_reveal(std::make_tuple(3)));
39 int ifu = 3;
40 BOOST_HOF_TEST_CHECK(3 == unary_unpack(std::tuple<int&>(ifu)));
41
42#if BOOST_HOF_HAS_CONSTEXPR_TUPLE
43 BOOST_HOF_STATIC_TEST_CHECK(3 == boost::hof::unpack(unary_class())(std::make_tuple(3)));
44 BOOST_HOF_STATIC_TEST_CHECK(3 == unary_unpack_constexpr(std::make_tuple(3)));
45 BOOST_HOF_STATIC_TEST_CHECK(3 == unary_unpack_reveal(std::make_tuple(3)));
46#endif
47}
48
49BOOST_HOF_TEST_CASE()
50{
51 BOOST_HOF_TEST_CHECK(3 == boost::hof::unpack(unary_class())(boost::hof::pack(3)));
52 BOOST_HOF_TEST_CHECK(3 == unary_unpack(boost::hof::pack(3)));
53 BOOST_HOF_TEST_CHECK(3 == unary_unpack_reveal(boost::hof::pack(3)));
54 int ifu = 3;
55 BOOST_HOF_TEST_CHECK(3 == unary_unpack(boost::hof::pack_forward(ifu)));
56
57 BOOST_HOF_STATIC_TEST_CHECK(3 == boost::hof::unpack(unary_class())(boost::hof::pack(3)));
58 BOOST_HOF_STATIC_TEST_CHECK(3 == unary_unpack_constexpr(boost::hof::pack(3)));
59 BOOST_HOF_STATIC_TEST_CHECK(3 == unary_unpack_reveal(boost::hof::pack(3)));
60}
61
62BOOST_HOF_TEST_CASE()
63{
64 BOOST_HOF_TEST_CHECK(3 == boost::hof::unpack(binary_class())(std::make_tuple(1, 2)));
65 BOOST_HOF_TEST_CHECK(3 == binary_unpack(std::make_tuple(1, 2)));
66 BOOST_HOF_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(1, 2)));
67
68 BOOST_HOF_TEST_CHECK(3 == boost::hof::unpack(binary_class())(std::make_tuple(1), std::make_tuple(2)));
69 BOOST_HOF_TEST_CHECK(3 == binary_unpack(std::make_tuple(1), std::make_tuple(2)));
70 BOOST_HOF_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(1), std::make_tuple(2)));
71
72 BOOST_HOF_TEST_CHECK(3 == boost::hof::unpack(binary_class())(std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
73 BOOST_HOF_TEST_CHECK(3 == binary_unpack(std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
74 BOOST_HOF_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
75
76 BOOST_HOF_TEST_CHECK(3 == boost::hof::unpack(binary_class())(std::make_tuple(), std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
77 BOOST_HOF_TEST_CHECK(3 == binary_unpack(std::make_tuple(), std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
78 BOOST_HOF_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(), std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
79
80 BOOST_HOF_TEST_CHECK(3 == boost::hof::unpack(binary_class())(std::make_tuple(1), std::make_tuple(), std::make_tuple(2), std::make_tuple()));
81 BOOST_HOF_TEST_CHECK(3 == binary_unpack(std::make_tuple(1), std::make_tuple(), std::make_tuple(2), std::make_tuple()));
82 BOOST_HOF_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(1), std::make_tuple(), std::make_tuple(2), std::make_tuple()));
83
84#if BOOST_HOF_HAS_CONSTEXPR_TUPLE
85 BOOST_HOF_STATIC_TEST_CHECK(3 == boost::hof::unpack(binary_class())(std::make_tuple(1, 2)));
86 BOOST_HOF_STATIC_TEST_CHECK(3 == binary_unpack_constexpr(std::make_tuple(1, 2)));
87 BOOST_HOF_STATIC_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(1, 2)));
88
89 BOOST_HOF_STATIC_TEST_CHECK(3 == boost::hof::unpack(binary_class())(std::make_tuple(1), std::make_tuple(2)));
90 BOOST_HOF_STATIC_TEST_CHECK(3 == binary_unpack_constexpr(std::make_tuple(1), std::make_tuple(2)));
91 BOOST_HOF_STATIC_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(1), std::make_tuple(2)));
92
93 BOOST_HOF_STATIC_TEST_CHECK(3 == boost::hof::unpack(binary_class())(std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
94 BOOST_HOF_STATIC_TEST_CHECK(3 == binary_unpack_constexpr(std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
95 BOOST_HOF_STATIC_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
96
97 BOOST_HOF_STATIC_TEST_CHECK(3 == boost::hof::unpack(binary_class())(std::make_tuple(), std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
98 BOOST_HOF_STATIC_TEST_CHECK(3 == binary_unpack_constexpr(std::make_tuple(), std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
99 BOOST_HOF_STATIC_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(), std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
100
101 BOOST_HOF_STATIC_TEST_CHECK(3 == boost::hof::unpack(binary_class())(std::make_tuple(1), std::make_tuple(), std::make_tuple(2), std::make_tuple()));
102 BOOST_HOF_STATIC_TEST_CHECK(3 == binary_unpack_constexpr(std::make_tuple(1), std::make_tuple(), std::make_tuple(2), std::make_tuple()));
103 BOOST_HOF_STATIC_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(1), std::make_tuple(), std::make_tuple(2), std::make_tuple()));
104#endif
105}
106
107BOOST_HOF_TEST_CASE()
108{
109 auto p1 = boost::hof::pack_basic(1, 2);
110 static_assert(boost::hof::is_unpackable<decltype(p1)>::value, "Not unpackable");
111 static_assert(boost::hof::is_unpackable<decltype((p1))>::value, "Not unpackable");
112
113 auto p2 = boost::hof::pack_forward(1, 2);
114 static_assert(boost::hof::is_unpackable<decltype(p2)>::value, "Not unpackable");
115 static_assert(boost::hof::is_unpackable<decltype((p2))>::value, "Not unpackable");
116
117 auto p3 = boost::hof::pack(1, 2);
118 static_assert(boost::hof::is_unpackable<decltype(p3)>::value, "Not unpackable");
119 static_assert(boost::hof::is_unpackable<decltype((p3))>::value, "Not unpackable");
120
121 static_assert(boost::hof::is_unpackable<std::tuple<int>>::value, "Not unpackable");
122
123 static_assert(!boost::hof::is_unpackable<int>::value, "Unpackable");
124 static_assert(!boost::hof::is_unpackable<void>::value, "Unpackable");
125}
126
127BOOST_HOF_TEST_CASE()
128{
129 typedef std::tuple<int, int> tuple_type;
130 static_assert(boost::hof::is_unpackable<tuple_type>::value, "Not unpackable");
131 static_assert(boost::hof::is_unpackable<tuple_type&>::value, "Not unpackable");
132 static_assert(boost::hof::is_unpackable<const tuple_type&>::value, "Not unpackable");
133 static_assert(boost::hof::is_unpackable<tuple_type&&>::value, "Not unpackable");
134
135}
136
137BOOST_HOF_STATIC_AUTO lambda_unary_unpack = boost::hof::unpack(BOOST_HOF_STATIC_LAMBDA(int x)
138{
139 return x;
140});
141
142BOOST_HOF_TEST_CASE()
143{
144 BOOST_HOF_TEST_CHECK(3 == lambda_unary_unpack(std::make_tuple(3)));
145}
146
147BOOST_HOF_TEST_CASE()
148{
149 BOOST_HOF_TEST_CHECK(3 == lambda_unary_unpack(boost::hof::pack(3)));
150}
151
152struct unary_move
153{
154 std::unique_ptr<int> i;
155 unary_move()
156 : i(new int(2))
157 {}
158
159 template<class T>
160 T operator()(T x) const
161 {
162 return x + *i;
163 }
164};
165
166static constexpr boost::hof::static_<boost::hof::unpack_adaptor<unary_move> > unary_move_unpack = {};
167
168BOOST_HOF_TEST_CASE()
169{
170 BOOST_HOF_TEST_CHECK(3 == boost::hof::unpack(unary_move())(std::make_tuple(1)));
171 BOOST_HOF_TEST_CHECK(3 == unary_move_unpack(std::make_tuple(1)));
172}
173
174BOOST_HOF_TEST_CASE()
175{
176 BOOST_HOF_TEST_CHECK(3 == boost::hof::unpack(unary_move())(boost::hof::pack(1)));
177 BOOST_HOF_TEST_CHECK(3 == unary_move_unpack(boost::hof::pack(1)));
178}
179
180struct indirect_sum_f
181{
182 template<class T, class U>
183 auto operator()(T x, U y) const
184 BOOST_HOF_RETURNS(*x + *y);
185};
186
187#define MAKE_UNIQUE_PTR(x) std::unique_ptr<int>(new int(x))
188
189BOOST_HOF_TEST_CASE()
190{
191 BOOST_HOF_TEST_CHECK(3 == boost::hof::unpack(indirect_sum_f())(boost::hof::pack_basic(MAKE_UNIQUE_PTR(1), MAKE_UNIQUE_PTR(2))));
192 BOOST_HOF_TEST_CHECK(3 == boost::hof::unpack(indirect_sum_f())(boost::hof::pack_forward(MAKE_UNIQUE_PTR(1), MAKE_UNIQUE_PTR(2))));
193 BOOST_HOF_TEST_CHECK(3 == boost::hof::unpack(indirect_sum_f())(boost::hof::pack(MAKE_UNIQUE_PTR(1), MAKE_UNIQUE_PTR(2))));
194 BOOST_HOF_TEST_CHECK(3 == boost::hof::unpack(indirect_sum_f())(std::make_tuple(MAKE_UNIQUE_PTR(1), MAKE_UNIQUE_PTR(2))));
195}
196
197template<class...>
198struct deduce_types
199{};
200
201struct deducer
202{
203 template<class... Ts>
204 deduce_types<Ts...> operator()(Ts&&...) const;
205};
206
207static constexpr boost::hof::unpack_adaptor<deducer> deduce = {};
208
209BOOST_HOF_TEST_CASE()
210{
211 STATIC_ASSERT_SAME(deduce_types<int, int>, decltype(deduce(std::make_tuple(1, 2))));
212 STATIC_ASSERT_SAME(deduce_types<int, int>, decltype(deduce(std::make_tuple(1), std::make_tuple(2))));
213 STATIC_ASSERT_SAME(deduce_types<int, int, int>, decltype(deduce(std::make_tuple(1), std::make_tuple(2), std::make_tuple(3))));
214 STATIC_ASSERT_SAME(std::tuple<int&&, int&&>, decltype(std::forward_as_tuple(1, 2)));
215 // Disable this test, it seems that rvalue references get swalllowed by type deduction
216 // STATIC_ASSERT_SAME(deduce_types<int&&, int&&>, decltype(deduce(std::forward_as_tuple(1, 2))));
217
218
219 STATIC_ASSERT_SAME(deduce_types<int, int>, decltype(deduce(boost::hof::pack_basic(1, 2))));
220 STATIC_ASSERT_SAME(deduce_types<int, int>, decltype(deduce(boost::hof::pack_basic(1), boost::hof::pack_basic(2))));
221 STATIC_ASSERT_SAME(deduce_types<int, int, int>, decltype(deduce(boost::hof::pack_basic(1), boost::hof::pack_basic(2), boost::hof::pack_basic(3))));
222 // STATIC_ASSERT_SAME(deduce_types<int&&, int&&>, decltype(deduce(boost::hof::pack_forward(1, 2))));
223}
224
225struct not_unpackable
226{};
227
228BOOST_HOF_TEST_CASE()
229{
230 auto f = boost::hof::unpack(boost::hof::always(1));
231
232 static_assert(!boost::hof::is_invocable<decltype(f), not_unpackable>::value, "SFINAE for unpack failed");
233}
234
235struct simple_unpackable
236{};
237
238namespace boost { namespace hof {
239
240template<>
241struct unpack_sequence<simple_unpackable>
242{
243 template<class F, class S>
244 constexpr static auto apply(F&& f, S&&) BOOST_HOF_RETURNS
245 (
246 f(1)
247 );
248};
249}} // namespace boost::hof
250
251BOOST_HOF_TEST_CASE()
252{
253 BOOST_HOF_TEST_CHECK(boost::hof::unpack(boost::hof::identity)(simple_unpackable{}) == 1);
254 BOOST_HOF_STATIC_TEST_CHECK(boost::hof::unpack(boost::hof::identity)(simple_unpackable{}) == 1);
255}
256

source code of boost/libs/hof/test/unpack.cpp