1 /*=============================================================================
2 Copyright (c) 2005-2006 Joao Abecasis
3 Copyright (c) 2006-2007 Tobias Schwinger
4
5 Use modification and distribution are subject to the Boost Software
6 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 http://www.boost.org/LICENSE_1_0.txt).
8 ==============================================================================*/
9
10 #include <boost/config.hpp>
11 #include <boost/fusion/functional/invocation/invoke.hpp>
12 #include <boost/detail/lightweight_test.hpp>
13
14 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
15 #include <functional>
16 #endif
17
18 #include <memory>
19 #include <boost/noncopyable.hpp>
20
21 #include <boost/type_traits/is_same.hpp>
22
23 #include <boost/mpl/int.hpp>
24
25 #include <boost/fusion/container/vector.hpp>
26 #include <boost/fusion/container/list.hpp>
27 #include <boost/fusion/sequence/intrinsic/size.hpp>
28 #include <boost/fusion/sequence/intrinsic/begin.hpp>
29 #include <boost/fusion/view/single_view.hpp>
30 #include <boost/fusion/view/iterator_range.hpp>
31 #include <boost/fusion/iterator/advance.hpp>
32 #include <boost/fusion/algorithm/transformation/join.hpp>
33
34 #include "../compile_time/sfinae_friendly.hpp"
35
36 namespace mpl = boost::mpl;
37 namespace fusion = boost::fusion;
38
39 template <typename T>
const_(T const & t)40 inline T const & const_(T const & t)
41 {
42 return t;
43 }
44
45 struct object {};
46 struct object_nc : boost::noncopyable {};
47
48 struct fobj
49 {
50 // Handle nullary separately to exercise result_of support
51 template <typename Sig>
52 struct result;
53
54 template <class Self, typename T0>
55 struct result< Self(T0) >
56 {
57 typedef int type;
58 };
59
60 template <class Self, typename T0, typename T1>
61 struct result< Self(T0, T1) >
62 {
63 typedef int type;
64 };
65
66 template <class Self, typename T0, typename T1, typename T2>
67 struct result< Self(T0, T1, T2) >
68 {
69 typedef int type;
70 };
71
operator ()fobj72 int operator()(int i) { return 2 + i; }
operator ()fobj73 int operator()(int i) const { return 3 + i; }
74
operator ()fobj75 int operator()(int i, object &) { return 4 + i; }
operator ()fobj76 int operator()(int i, object &) const { return 5 + i; }
operator ()fobj77 int operator()(int i, object const &) { return 6 + i; }
operator ()fobj78 int operator()(int i, object const &) const { return 7 + i; }
79
operator ()fobj80 int operator()(int i, object &, object_nc &) { return 10 + i; }
operator ()fobj81 int operator()(int i, object &, object_nc &) const { return 11 + i; }
82 int operator()(int i, object const &, object_nc &);
83 int operator()(int i, object const &, object_nc &) const;
84 };
85 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<fobj, sfinae_friendly::v0>));
86 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<fobj, sfinae_friendly::v1>));
87 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<fobj, sfinae_friendly::v2>));
88 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<fobj, sfinae_friendly::v3>));
89
90
91 struct nullary_fobj
92 {
93 typedef int result_type;
94
operator ()nullary_fobj95 int operator()() { return 0; }
operator ()nullary_fobj96 int operator()() const { return 1; }
97 };
98 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<nullary_fobj, sfinae_friendly::v1>));
99 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<nullary_fobj, sfinae_friendly::v2>));
100 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<nullary_fobj, sfinae_friendly::v3>));
101
102
103 struct fobj_nc
104 : boost::noncopyable
105 {
106 // Handle nullary separately to exercise result_of support
107 template <typename Sig>
108 struct result;
109
110 template <class Self, typename T0>
111 struct result< Self(T0)>
112 {
113 typedef int type;
114 };
115
operator ()fobj_nc116 int operator()(int i) { return 14 + i; }
operator ()fobj_nc117 int operator()(int i) const { return 15 + i; }
118 };
119 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<fobj_nc, sfinae_friendly::v0>));
120 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<fobj_nc, sfinae_friendly::v1>));
121 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<fobj_nc, sfinae_friendly::v2>));
122 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<fobj_nc, sfinae_friendly::v3>));
123
124
125 struct nullary_fobj_nc
126 : boost::noncopyable
127 {
128 typedef int result_type;
129
operator ()nullary_fobj_nc130 int operator()() { return 12; }
operator ()nullary_fobj_nc131 int operator()() const { return 13; }
132 };
133 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<nullary_fobj_nc, sfinae_friendly::v1>));
134 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<nullary_fobj_nc, sfinae_friendly::v2>));
135 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<nullary_fobj_nc, sfinae_friendly::v3>));
136
137
nullary()138 int nullary() { return 16; }
unary(int i)139 int unary(int i) { return 17 + i; }
binary1(int i,object &)140 int binary1(int i, object &) { return 18 + i; }
binary2(int i,object const &)141 int binary2(int i, object const &) { return 19 + i; }
142 //FIXME
143 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<int(*)(), sfinae_friendly::v1>));
144 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<int(*)(), sfinae_friendly::v2>));
145 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<int(*)(), sfinae_friendly::v3>));
146 //
147 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<int(*)(int), sfinae_friendly::v0>));
148 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<int(*)(int), sfinae_friendly::v1>));
149 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<int(*)(int), sfinae_friendly::v2>));
150 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<int(*)(int), sfinae_friendly::v3>));
151 //
152 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<int(*)(int, object &), sfinae_friendly::v0>));
153 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<int(*)(int, object &), sfinae_friendly::v1>));
154 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<int(*)(int, object &), sfinae_friendly::v2>));
155 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<int(*)(int, object &), sfinae_friendly::v3>));
156 //
157 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<int(*)(int, object const &), sfinae_friendly::v0>));
158 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<int(*)(int, object const &), sfinae_friendly::v1>));
159 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<int(*)(int, object const &), sfinae_friendly::v2>));
160 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<int(*)(int, object const &), sfinae_friendly::v3>));
161
162 typedef int (* func_ptr)(int);
163 typedef int (* const c_func_ptr)(int);
164 typedef int (* volatile v_func_ptr)(int);
165 typedef int (* const volatile cv_func_ptr)(int);
166
167 func_ptr func_ptr1 = &unary;
168 c_func_ptr func_ptr2 = &unary;
169 v_func_ptr func_ptr3 = &unary;
170 cv_func_ptr func_ptr4 = &unary;
171
172 class members
173 {
174 public:
175 int data;
176
members()177 members()
178 : data(20)
179 { }
180
nullary()181 int nullary() { return data + 1; }
nullary_c() const182 int nullary_c() const { return data + 2; }
unary(int i)183 int unary(int i) { return data + 3 + i; }
unary_c(int i) const184 int unary_c(int i) const { return data + 4 + i; }
binary(int i,object)185 int binary(int i, object) { return data + 5 + i; }
binary_c(int i,object) const186 int binary_c(int i, object) const { return data + 6 + i; }
187 };
188
189 #ifdef BOOST_NO_CXX11_SMART_PTR
190 typedef std::auto_ptr<members > members_ptr;
191 typedef std::auto_ptr<members const> const_members_ptr;
192 #else
193 typedef std::unique_ptr<members > members_ptr;
194 typedef std::unique_ptr<members const> const_members_ptr;
195 #endif
196
197 struct derived
198 : members
199 {
200 };
201
202 #ifdef BOOST_NO_CXX11_SMART_PTR
203 typedef std::auto_ptr<derived > derived_ptr;
204 typedef std::auto_ptr<derived const> const_derived_ptr;
205 #else
206 typedef std::unique_ptr<derived > derived_ptr;
207 typedef std::unique_ptr<derived const> const_derived_ptr;
208 #endif
209
210
211 typedef int element1_type;
212 typedef object element2_type;
213 typedef object_nc & element3_type;
214
215 int element1 = 100;
216 object element2 = object();
217 object_nc element3;
218
219 members that;
220
221 members_ptr spt_that(new members);
222 const_members_ptr spt_that_c(new members);
223
224 typedef fusion::single_view<members > sv_obj;
225 typedef fusion::single_view<members &> sv_ref;
226 typedef fusion::single_view<members *> sv_ptr;
227 typedef fusion::single_view<members const > sv_obj_c;
228 typedef fusion::single_view<members const &> sv_ref_c;
229 typedef fusion::single_view<members const *> sv_ptr_c;
230 typedef fusion::single_view<members_ptr const &> sv_spt;
231 typedef fusion::single_view<const_members_ptr const &> sv_spt_c;
232
233 sv_obj sv_obj_ctx( that);
234 sv_ref sv_ref_ctx( that);
235 sv_ptr sv_ptr_ctx(& that);
236 sv_obj_c sv_obj_c_ctx( that);
237 sv_ref_c sv_ref_c_ctx( that);
238 sv_ptr_c sv_ptr_c_ctx(& that);
239 sv_spt sv_spt_ctx(spt_that);
240 sv_spt_c sv_spt_c_ctx(spt_that_c);
241 template <typename F, typename S>
242 struct sv_helper
243 {
244 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<F, typename fusion::result_of::join<sv_obj , S>::type>));
245 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<F, typename fusion::result_of::join<sv_ref , S>::type>));
246 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<F, typename fusion::result_of::join<sv_ptr , S>::type>));
247 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<F, typename fusion::result_of::join<sv_obj_c, S>::type>));
248 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<F, typename fusion::result_of::join<sv_ref_c, S>::type>));
249 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<F, typename fusion::result_of::join<sv_ptr_c, S>::type>));
250 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<F, typename fusion::result_of::join<sv_spt , S>::type>));
251 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<F, typename fusion::result_of::join<sv_spt_c, S>::type>));
252 };
253 // FIXME:
254 //template struct sv_helper<int (members::*)() , sfinae_friendly::v1>;
255 //template struct sv_helper<int (members::*)() , sfinae_friendly::v2>;
256 //template struct sv_helper<int (members::*)() , sfinae_friendly::v3>;
257 //template struct sv_helper<int (members::*)() const, sfinae_friendly::v1>;
258 //template struct sv_helper<int (members::*)() const, sfinae_friendly::v2>;
259 //template struct sv_helper<int (members::*)() const, sfinae_friendly::v3>;
260
261 //template struct sv_helper<int (members::*)(int) , sfinae_friendly::v0>;
262 //template struct sv_helper<int (members::*)(int) , sfinae_friendly::v1>;
263 //template struct sv_helper<int (members::*)(int) , sfinae_friendly::v2>;
264 //template struct sv_helper<int (members::*)(int) , sfinae_friendly::v3>;
265 //template struct sv_helper<int (members::*)(int) const, sfinae_friendly::v0>;
266 //template struct sv_helper<int (members::*)(int) const, sfinae_friendly::v1>;
267 //template struct sv_helper<int (members::*)(int) const, sfinae_friendly::v2>;
268 //template struct sv_helper<int (members::*)(int) const, sfinae_friendly::v3>;
269
270 //template struct sv_helper<int (members::*)(int, object) , sfinae_friendly::v0>;
271 //template struct sv_helper<int (members::*)(int, object) , sfinae_friendly::v1>;
272 //template struct sv_helper<int (members::*)(int, object) , sfinae_friendly::v2>;
273 //template struct sv_helper<int (members::*)(int, object) , sfinae_friendly::v3>;
274 //template struct sv_helper<int (members::*)(int, object) const, sfinae_friendly::v0>;
275 //template struct sv_helper<int (members::*)(int, object) const, sfinae_friendly::v1>;
276 //template struct sv_helper<int (members::*)(int, object) const, sfinae_friendly::v2>;
277 //template struct sv_helper<int (members::*)(int, object) const, sfinae_friendly::v3>;
278
279 derived derived_that;
280
281 derived_ptr spt_derived_that(new derived);
282 const_derived_ptr spt_derived_that_c(new derived);
283
284 typedef fusion::single_view<derived > sv_obj_d;
285 typedef fusion::single_view<derived &> sv_ref_d;
286 typedef fusion::single_view<derived *> sv_ptr_d;
287 typedef fusion::single_view<derived const > sv_obj_c_d;
288 typedef fusion::single_view<derived const &> sv_ref_c_d;
289 typedef fusion::single_view<derived const *> sv_ptr_c_d;
290 typedef fusion::single_view<derived_ptr const &> sv_spt_d;
291 typedef fusion::single_view<const_derived_ptr const &> sv_spt_c_d;
292
293 sv_obj_d sv_obj_d_ctx( derived_that);
294 sv_ref_d sv_ref_d_ctx( derived_that);
295 sv_ptr_d sv_ptr_d_ctx(& derived_that);
296 sv_obj_c_d sv_obj_c_d_ctx( derived_that);
297 sv_ref_c_d sv_ref_c_d_ctx( derived_that);
298 sv_ptr_c_d sv_ptr_c_d_ctx(& derived_that);
299 sv_spt_d sv_spt_d_ctx(spt_derived_that);
300 sv_spt_c_d sv_spt_c_d_ctx(spt_derived_that_c);
301 template <typename F, typename S>
302 struct sv_d_helper
303 {
304 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<F, typename fusion::result_of::join<sv_obj_d , S>::type>));
305 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<F, typename fusion::result_of::join<sv_ref_d , S>::type>));
306 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<F, typename fusion::result_of::join<sv_ptr_d , S>::type>));
307 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<F, typename fusion::result_of::join<sv_obj_c_d, S>::type>));
308 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<F, typename fusion::result_of::join<sv_ref_c_d, S>::type>));
309 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<F, typename fusion::result_of::join<sv_ptr_c_d, S>::type>));
310 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<F, typename fusion::result_of::join<sv_spt_d , S>::type>));
311 SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke<F, typename fusion::result_of::join<sv_spt_c_d, S>::type>));
312 };
313 // FIXME:
314 //template struct sv_d_helper<int (members::*)() , sfinae_friendly::v1>;
315 //template struct sv_d_helper<int (members::*)() , sfinae_friendly::v2>;
316 //template struct sv_d_helper<int (members::*)() , sfinae_friendly::v3>;
317 //template struct sv_d_helper<int (members::*)() const, sfinae_friendly::v1>;
318 //template struct sv_d_helper<int (members::*)() const, sfinae_friendly::v2>;
319 //template struct sv_d_helper<int (members::*)() const, sfinae_friendly::v3>;
320
321 //template struct sv_d_helper<int (members::*)(int) , sfinae_friendly::v0>;
322 //template struct sv_d_helper<int (members::*)(int) , sfinae_friendly::v1>;
323 //template struct sv_d_helper<int (members::*)(int) , sfinae_friendly::v2>;
324 //template struct sv_d_helper<int (members::*)(int) , sfinae_friendly::v3>;
325 //template struct sv_d_helper<int (members::*)(int) const, sfinae_friendly::v0>;
326 //template struct sv_d_helper<int (members::*)(int) const, sfinae_friendly::v1>;
327 //template struct sv_d_helper<int (members::*)(int) const, sfinae_friendly::v2>;
328 //template struct sv_d_helper<int (members::*)(int) const, sfinae_friendly::v3>;
329
330 //template struct sv_d_helper<int (members::*)(int, object) , sfinae_friendly::v0>;
331 //template struct sv_d_helper<int (members::*)(int, object) , sfinae_friendly::v1>;
332 //template struct sv_d_helper<int (members::*)(int, object) , sfinae_friendly::v2>;
333 //template struct sv_d_helper<int (members::*)(int, object) , sfinae_friendly::v3>;
334 //template struct sv_d_helper<int (members::*)(int, object) const, sfinae_friendly::v0>;
335 //template struct sv_d_helper<int (members::*)(int, object) const, sfinae_friendly::v1>;
336 //template struct sv_d_helper<int (members::*)(int, object) const, sfinae_friendly::v2>;
337 //template struct sv_d_helper<int (members::*)(int, object) const, sfinae_friendly::v3>;
338
339 template <class Sequence>
test_sequence_n(Sequence & seq,mpl::int_<0>)340 void test_sequence_n(Sequence & seq, mpl::int_<0>)
341 {
342 // Function Objects
343
344 nullary_fobj f;
345
346 BOOST_TEST(f () == fusion::invoke(f , seq ));
347 BOOST_TEST(f () == fusion::invoke(f , const_(seq)));
348
349 // Note: The function object is taken by value, so we request the copy
350 // to be const with an explicit template argument. We can also request
351 // the function object to be pased by reference...
352 BOOST_TEST(const_(f)() == fusion::invoke<nullary_fobj const >(const_(f), seq ));
353 BOOST_TEST(const_(f)() == fusion::invoke<nullary_fobj const &>(const_(f), const_(seq)));
354
355 nullary_fobj_nc nc_f;
356 // ...and we further ensure there is no copying in this case, using a
357 // noncopyable function object.
358 BOOST_TEST(nc_f () == fusion::invoke<nullary_fobj_nc &>(nc_f , seq ));
359 BOOST_TEST(nc_f () == fusion::invoke<nullary_fobj_nc &>(nc_f , const_(seq)));
360 BOOST_TEST(const_(nc_f)() == fusion::invoke<nullary_fobj_nc const &>(const_(nc_f), seq ));
361 BOOST_TEST(const_(nc_f)() == fusion::invoke<nullary_fobj_nc const &>(const_(nc_f), const_(seq)));
362
363 // Builtin Functions
364
365 // Call through ref/ptr to function
366 BOOST_TEST(nullary() == fusion::invoke<int (&)()>(nullary, seq));
367 BOOST_TEST(nullary() == fusion::invoke(& nullary, seq));
368
369 // Call through ptr to member function
370 // Note: The non-const function members::nullary can't be invoked with
371 // fusion::join(sv_obj_ctx,seq)), which is const and so is its first element
372 BOOST_TEST(that.nullary() == fusion::invoke(& members::nullary, fusion::join(sv_ref_ctx,seq)));
373 BOOST_TEST(that.nullary() == fusion::invoke(& members::nullary, fusion::join(sv_ptr_ctx,seq)));
374 BOOST_TEST(that.nullary() == fusion::invoke(& members::nullary, fusion::join(sv_spt_ctx,seq)));
375 BOOST_TEST(that.nullary_c() == fusion::invoke(& members::nullary_c, fusion::join(sv_obj_ctx,seq)));
376 BOOST_TEST(that.nullary_c() == fusion::invoke(& members::nullary_c, fusion::join(sv_ref_ctx,seq)));
377 BOOST_TEST(that.nullary_c() == fusion::invoke(& members::nullary_c, fusion::join(sv_ptr_ctx,seq)));
378 BOOST_TEST(that.nullary_c() == fusion::invoke(& members::nullary_c, fusion::join(sv_spt_ctx,seq)));
379 BOOST_TEST(that.nullary_c() == fusion::invoke(& members::nullary_c, fusion::join(sv_obj_c_ctx,seq)));
380 BOOST_TEST(that.nullary_c() == fusion::invoke(& members::nullary_c, fusion::join(sv_ref_c_ctx,seq)));
381 BOOST_TEST(that.nullary_c() == fusion::invoke(& members::nullary_c, fusion::join(sv_ptr_c_ctx,seq)));
382 BOOST_TEST(that.nullary_c() == fusion::invoke(& members::nullary_c, fusion::join(sv_spt_c_ctx,seq)));
383
384 // Pointer to data member
385
386 // $$$ JDG $$$ disabling this test due to C++11 error: assignment of read-only location
387 //~ BOOST_TEST(that.data == (fusion::invoke(& members::data, fusion::join(sv_obj_ctx,seq)) = that.data));
388 BOOST_TEST(that.data == (fusion::invoke(& members::data, fusion::join(sv_ref_ctx,seq)) = that.data));
389 BOOST_TEST(that.data == (fusion::invoke(& members::data, fusion::join(sv_ptr_ctx,seq)) = that.data));
390 BOOST_TEST(that.data == (fusion::invoke(& members::data, fusion::join(sv_spt_ctx,seq)) = that.data));
391 // disabling this test, since it tries to return local address which is undefined behavior
392 //~ BOOST_TEST(that.data == fusion::invoke(& members::data, fusion::join(sv_obj_c_ctx,seq)));
393 BOOST_TEST(that.data == fusion::invoke(& members::data, fusion::join(sv_ref_c_ctx,seq)));
394 BOOST_TEST(that.data == fusion::invoke(& members::data, fusion::join(sv_ptr_c_ctx,seq)));
395 BOOST_TEST(that.data == fusion::invoke(& members::data, fusion::join(sv_spt_c_ctx,seq)));
396
397 // $$$ JDG $$$ disabling this test due to C++11 error: assignment of read-only location
398 //~ BOOST_TEST(that.data == (fusion::invoke(& members::data, fusion::join(sv_obj_d_ctx,seq)) = that.data));
399 BOOST_TEST(that.data == (fusion::invoke(& members::data, fusion::join(sv_ref_d_ctx,seq)) = that.data));
400 BOOST_TEST(that.data == (fusion::invoke(& members::data, fusion::join(sv_ptr_d_ctx,seq)) = that.data));
401 BOOST_TEST(that.data == (fusion::invoke(& members::data, fusion::join(sv_spt_d_ctx,seq)) = that.data));
402 // disabling this test, since it tries to return local address which is undefined behavior
403 //~ BOOST_TEST(that.data == fusion::invoke(& members::data, fusion::join(sv_obj_c_d_ctx,seq)));
404 BOOST_TEST(that.data == fusion::invoke(& members::data, fusion::join(sv_ref_c_d_ctx,seq)));
405 BOOST_TEST(that.data == fusion::invoke(& members::data, fusion::join(sv_ptr_c_d_ctx,seq)));
406 BOOST_TEST(that.data == fusion::invoke(& members::data, fusion::join(sv_spt_c_d_ctx,seq)));
407 }
408
409 template <class Sequence>
test_sequence_n(Sequence & seq,mpl::int_<1>)410 void test_sequence_n(Sequence & seq, mpl::int_<1>)
411 {
412 fobj f;
413 BOOST_TEST(f(element1) == fusion::invoke(f , seq ));
414 BOOST_TEST(f(element1) == fusion::invoke(f , const_(seq)));
415 BOOST_TEST(const_(f)(element1) == fusion::invoke<fobj const >(const_(f), seq ));
416 BOOST_TEST(const_(f)(element1) == fusion::invoke<fobj const &>(const_(f), const_(seq)));
417
418 fobj_nc nc_f;
419 BOOST_TEST(nc_f(element1) == fusion::invoke<fobj_nc &>(nc_f, seq ));
420 BOOST_TEST(nc_f(element1) == fusion::invoke<fobj_nc &>(nc_f, const_(seq)));
421 BOOST_TEST(const_(nc_f)(element1) == fusion::invoke<fobj_nc const &>(const_(nc_f), seq ));
422 BOOST_TEST(const_(nc_f)(element1) == fusion::invoke<fobj_nc const &>(const_(nc_f), const_(seq)));
423
424 BOOST_TEST(unary(element1) == fusion::invoke<int (&)(int)>(unary, seq));
425 BOOST_TEST(func_ptr1(element1) == fusion::invoke(func_ptr1, seq));
426 BOOST_TEST(func_ptr2(element1) == fusion::invoke(func_ptr2, seq));
427 BOOST_TEST(func_ptr3(element1) == fusion::invoke(func_ptr3, seq));
428 BOOST_TEST(func_ptr4(element1) == fusion::invoke(func_ptr4, seq));
429
430 BOOST_TEST(that.unary(element1) == fusion::invoke(& members::unary, fusion::join(sv_ref_ctx,seq)));
431 BOOST_TEST(that.unary(element1) == fusion::invoke(& members::unary, fusion::join(sv_ptr_ctx,seq)));
432 BOOST_TEST(that.unary(element1) == fusion::invoke(& members::unary, fusion::join(sv_spt_ctx,seq)));
433 BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_obj_ctx,seq)));
434 BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_ref_ctx,seq)));
435 BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_ptr_ctx,seq)));
436 BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_spt_ctx,seq)));
437 BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_obj_c_ctx,seq)));
438 BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_ref_c_ctx,seq)));
439 BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_ptr_c_ctx,seq)));
440 BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_spt_c_ctx,seq)));
441
442 BOOST_TEST(that.unary(element1) == fusion::invoke(& members::unary, fusion::join(sv_ref_d_ctx,seq)));
443 BOOST_TEST(that.unary(element1) == fusion::invoke(& members::unary, fusion::join(sv_ptr_d_ctx,seq)));
444 BOOST_TEST(that.unary(element1) == fusion::invoke(& members::unary, fusion::join(sv_spt_d_ctx,seq)));
445 BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_obj_d_ctx,seq)));
446 BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_ref_d_ctx,seq)));
447 BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_ptr_d_ctx,seq)));
448 BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_spt_d_ctx,seq)));
449 BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_obj_c_d_ctx,seq)));
450 BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_ref_c_d_ctx,seq)));
451 BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_ptr_c_d_ctx,seq)));
452 BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_spt_c_d_ctx,seq)));
453 }
454
455 template <class Sequence>
test_sequence_n(Sequence & seq,mpl::int_<2>)456 void test_sequence_n(Sequence & seq, mpl::int_<2>)
457 {
458 fobj f;
459 BOOST_TEST(f (element1, element2) == fusion::invoke(f , seq));
460 BOOST_TEST(f (element1, const_(element2)) == fusion::invoke(f , const_(seq)));
461 BOOST_TEST(const_(f)(element1, element2) == fusion::invoke<fobj const>(const_(f), seq));
462 BOOST_TEST(const_(f)(element1, const_(element2)) == fusion::invoke<fobj const>(const_(f), const_(seq)));
463
464 BOOST_TEST(binary1(element1, element2) == fusion::invoke(binary1, seq));
465 BOOST_TEST(binary2(element1, element2) == fusion::invoke(binary2, seq));
466
467 BOOST_TEST(that.binary(element1,element2) == fusion::invoke(& members::binary, fusion::join(sv_ref_ctx,seq)));
468 BOOST_TEST(that.binary(element1,element2) == fusion::invoke(& members::binary, fusion::join(sv_ptr_ctx,seq)));
469 BOOST_TEST(that.binary(element1,element2) == fusion::invoke(& members::binary, fusion::join(sv_spt_ctx,seq)));
470 BOOST_TEST(that.binary_c(element1,element2) == fusion::invoke(& members::binary_c, fusion::join(sv_obj_ctx,seq)));
471 BOOST_TEST(that.binary_c(element1,element2) == fusion::invoke(& members::binary_c, fusion::join(sv_ref_ctx,seq)));
472 BOOST_TEST(that.binary_c(element1,element2) == fusion::invoke(& members::binary_c, fusion::join(sv_ptr_ctx,seq)));
473 BOOST_TEST(that.binary_c(element1,element2) == fusion::invoke(& members::binary_c, fusion::join(sv_spt_ctx,seq)));
474 BOOST_TEST(that.binary_c(element1,element2) == fusion::invoke(& members::binary_c, fusion::join(sv_obj_c_ctx,seq)));
475 BOOST_TEST(that.binary_c(element1,element2) == fusion::invoke(& members::binary_c, fusion::join(sv_ref_c_ctx,seq)));
476 BOOST_TEST(that.binary_c(element1,element2) == fusion::invoke(& members::binary_c, fusion::join(sv_ptr_c_ctx,seq)));
477 BOOST_TEST(that.binary_c(element1,element2) == fusion::invoke(& members::binary_c, fusion::join(sv_spt_c_ctx,seq)));
478 }
479
480 template <class Sequence>
test_sequence_n(Sequence & seq,mpl::int_<3>)481 void test_sequence_n(Sequence & seq, mpl::int_<3>)
482 {
483 fobj f;
484
485 BOOST_TEST(f(element1, element2, element3) == fusion::invoke(f, seq));
486 BOOST_TEST(const_(f)(element1, element2, element3) == fusion::invoke<fobj const>(const_(f), seq));
487 }
488
489 template <class Sequence>
test_sequence(Sequence & seq)490 void test_sequence(Sequence & seq)
491 {
492 test_sequence_n(seq, mpl::int_<boost::fusion::result_of::size<Sequence>::value>());
493 }
494
495
result_type_tests()496 void result_type_tests()
497 {
498 using boost::is_same;
499
500 BOOST_TEST(( is_same<
501 boost::fusion::result_of::invoke<int (*)(), fusion::vector0<> >::type, int
502 >::value ));
503 // disabled until boost::result_of supports it
504 // BOOST_TEST(( is_same<
505 // boost::fusion::result_of::invoke<int (*)(...), fusion::vector1<int> >::type, int
506 // >::value ));
507 BOOST_TEST(( is_same<
508 boost::fusion::result_of::invoke<int (members::*)(), fusion::vector1<members*> >::type, int
509 >::value ));
510 // disabled until boost::result_of supports it
511 // BOOST_TEST(( is_same<
512 // boost::fusion::result_of::invoke<int (members::*)(...), fusion::vector2<members*,int> >::type, int
513 // >::value ));
514 }
515
main()516 int main()
517 {
518 result_type_tests();
519
520 typedef fusion::vector<> vector0;
521 typedef fusion::vector<element1_type> vector1;
522 typedef fusion::vector<element1_type, element2_type> vector2;
523 typedef fusion::vector<element1_type, element2_type, element3_type> vector3;
524
525 vector0 v0;
526 vector1 v1(element1);
527 vector2 v2(element1, element2);
528
529 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
530 // Note: C++11 will pickup the rvalue overload for the d argument
531 // since we do not have all permutations (expensive!) for all const&
532 // and && arguments. We either have all && or all const& arguments only.
533 // For that matter, use std::ref to disambiguate the call.
534
535 vector3 v3(element1, element2, std::ref(element3));
536 #else
537 vector3 v3(element1, element2, element3);
538 #endif
539
540 test_sequence(v0);
541 test_sequence(v1);
542 test_sequence(v2);
543 test_sequence(v3);
544
545 typedef fusion::list<> list0;
546 typedef fusion::list<element1_type> list1;
547 typedef fusion::list<element1_type, element2_type> list2;
548 typedef fusion::list<element1_type, element2_type, element3_type> list3;
549
550 list0 l0;
551 list1 l1(element1);
552 list2 l2(element1, element2);
553 list3 l3(element1, element2, element3);
554
555 test_sequence(l0);
556 test_sequence(l1);
557 test_sequence(l2);
558 test_sequence(l3);
559
560 return boost::report_errors();
561 }
562
563