• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
14 static constexpr boost::hof::static_<boost::hof::unpack_adaptor<unary_class> > unary_unpack = {};
15 static constexpr boost::hof::static_<boost::hof::unpack_adaptor<binary_class> > binary_unpack = {};
16 
17 BOOST_HOF_STATIC_AUTO unary_unpack_constexpr = boost::hof::unpack_adaptor<unary_class>();
18 #if BOOST_HOF_HAS_CONSTEXPR_TUPLE
19 BOOST_HOF_STATIC_AUTO binary_unpack_constexpr = boost::hof::unpack_adaptor<binary_class>();
20 #endif
21 
22 BOOST_HOF_STATIC_AUTO unary_unpack_reveal = boost::hof::reveal_adaptor<boost::hof::unpack_adaptor<unary_class>>();
23 BOOST_HOF_STATIC_AUTO binary_unpack_reveal = boost::hof::reveal_adaptor<boost::hof::unpack_adaptor<binary_class>>();
24 
25 #if BOOST_HOF_HAS_NOEXCEPT_DEDUCTION
BOOST_HOF_TEST_CASE()26 BOOST_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 
BOOST_HOF_TEST_CASE()34 BOOST_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 
BOOST_HOF_TEST_CASE()49 BOOST_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 
BOOST_HOF_TEST_CASE()62 BOOST_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 
BOOST_HOF_TEST_CASE()107 BOOST_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 
BOOST_HOF_TEST_CASE()127 BOOST_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 
137 BOOST_HOF_STATIC_AUTO lambda_unary_unpack = boost::hof::unpack(BOOST_HOF_STATIC_LAMBDA(int x)
138 {
139     return x;
140 });
141 
BOOST_HOF_TEST_CASE()142 BOOST_HOF_TEST_CASE()
143 {
144     BOOST_HOF_TEST_CHECK(3 == lambda_unary_unpack(std::make_tuple(3)));
145 }
146 
BOOST_HOF_TEST_CASE()147 BOOST_HOF_TEST_CASE()
148 {
149     BOOST_HOF_TEST_CHECK(3 == lambda_unary_unpack(boost::hof::pack(3)));
150 }
151 
152 struct unary_move
153 {
154     std::unique_ptr<int> i;
unary_moveunary_move155     unary_move()
156     : i(new int(2))
157     {}
158 
159     template<class T>
operator ()unary_move160     T operator()(T x) const
161     {
162         return x + *i;
163     }
164 };
165 
166 static constexpr boost::hof::static_<boost::hof::unpack_adaptor<unary_move> > unary_move_unpack = {};
167 
BOOST_HOF_TEST_CASE()168 BOOST_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 
BOOST_HOF_TEST_CASE()174 BOOST_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 
180 struct 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 
BOOST_HOF_TEST_CASE()189 BOOST_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 
197 template<class...>
198 struct deduce_types
199 {};
200 
201 struct deducer
202 {
203     template<class... Ts>
204     deduce_types<Ts...> operator()(Ts&&...) const;
205 };
206 
207 static constexpr boost::hof::unpack_adaptor<deducer> deduce = {};
208 
BOOST_HOF_TEST_CASE()209 BOOST_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 
225 struct not_unpackable
226 {};
227 
BOOST_HOF_TEST_CASE()228 BOOST_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 
235 struct simple_unpackable
236 {};
237 
238 namespace boost { namespace hof {
239 
240 template<>
241 struct 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 
BOOST_HOF_TEST_CASE()251 BOOST_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