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     BOOST_TEST(that.data == fusion::invoke(& members::data, fusion::join(sv_obj_c_ctx,seq)));
392     BOOST_TEST(that.data == fusion::invoke(& members::data, fusion::join(sv_ref_c_ctx,seq)));
393     BOOST_TEST(that.data == fusion::invoke(& members::data, fusion::join(sv_ptr_c_ctx,seq)));
394     BOOST_TEST(that.data == fusion::invoke(& members::data, fusion::join(sv_spt_c_ctx,seq)));
395 
396     // $$$ JDG $$$ disabling this test due to C++11 error: assignment of read-only location
397     //~ BOOST_TEST(that.data == (fusion::invoke(& members::data, fusion::join(sv_obj_d_ctx,seq)) = that.data));
398     BOOST_TEST(that.data == (fusion::invoke(& members::data, fusion::join(sv_ref_d_ctx,seq)) = that.data));
399     BOOST_TEST(that.data == (fusion::invoke(& members::data, fusion::join(sv_ptr_d_ctx,seq)) = that.data));
400     BOOST_TEST(that.data == (fusion::invoke(& members::data, fusion::join(sv_spt_d_ctx,seq)) = that.data));
401     BOOST_TEST(that.data == fusion::invoke(& members::data, fusion::join(sv_obj_c_d_ctx,seq)));
402     BOOST_TEST(that.data == fusion::invoke(& members::data, fusion::join(sv_ref_c_d_ctx,seq)));
403     BOOST_TEST(that.data == fusion::invoke(& members::data, fusion::join(sv_ptr_c_d_ctx,seq)));
404     BOOST_TEST(that.data == fusion::invoke(& members::data, fusion::join(sv_spt_c_d_ctx,seq)));
405 }
406 
407 template <class Sequence>
test_sequence_n(Sequence & seq,mpl::int_<1>)408 void test_sequence_n(Sequence & seq, mpl::int_<1>)
409 {
410     fobj f;
411     BOOST_TEST(f(element1) == fusion::invoke(f , seq ));
412     BOOST_TEST(f(element1) == fusion::invoke(f , const_(seq)));
413     BOOST_TEST(const_(f)(element1) == fusion::invoke<fobj const  >(const_(f), seq ));
414     BOOST_TEST(const_(f)(element1) == fusion::invoke<fobj const &>(const_(f), const_(seq)));
415 
416     fobj_nc nc_f;
417     BOOST_TEST(nc_f(element1) == fusion::invoke<fobj_nc &>(nc_f, seq ));
418     BOOST_TEST(nc_f(element1) == fusion::invoke<fobj_nc &>(nc_f, const_(seq)));
419     BOOST_TEST(const_(nc_f)(element1) == fusion::invoke<fobj_nc const &>(const_(nc_f), seq ));
420     BOOST_TEST(const_(nc_f)(element1) == fusion::invoke<fobj_nc const &>(const_(nc_f), const_(seq)));
421 
422     BOOST_TEST(unary(element1) == fusion::invoke<int (&)(int)>(unary, seq));
423     BOOST_TEST(func_ptr1(element1) == fusion::invoke(func_ptr1, seq));
424     BOOST_TEST(func_ptr2(element1) == fusion::invoke(func_ptr2, seq));
425     BOOST_TEST(func_ptr3(element1) == fusion::invoke(func_ptr3, seq));
426     BOOST_TEST(func_ptr4(element1) == fusion::invoke(func_ptr4, seq));
427 
428     BOOST_TEST(that.unary(element1) == fusion::invoke(& members::unary, fusion::join(sv_ref_ctx,seq)));
429     BOOST_TEST(that.unary(element1) == fusion::invoke(& members::unary, fusion::join(sv_ptr_ctx,seq)));
430     BOOST_TEST(that.unary(element1) == fusion::invoke(& members::unary, fusion::join(sv_spt_ctx,seq)));
431     BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_obj_ctx,seq)));
432     BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_ref_ctx,seq)));
433     BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_ptr_ctx,seq)));
434     BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_spt_ctx,seq)));
435     BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_obj_c_ctx,seq)));
436     BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_ref_c_ctx,seq)));
437     BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_ptr_c_ctx,seq)));
438     BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_spt_c_ctx,seq)));
439 
440     BOOST_TEST(that.unary(element1) == fusion::invoke(& members::unary, fusion::join(sv_ref_d_ctx,seq)));
441     BOOST_TEST(that.unary(element1) == fusion::invoke(& members::unary, fusion::join(sv_ptr_d_ctx,seq)));
442     BOOST_TEST(that.unary(element1) == fusion::invoke(& members::unary, fusion::join(sv_spt_d_ctx,seq)));
443     BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_obj_d_ctx,seq)));
444     BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_ref_d_ctx,seq)));
445     BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_ptr_d_ctx,seq)));
446     BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_spt_d_ctx,seq)));
447     BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_obj_c_d_ctx,seq)));
448     BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_ref_c_d_ctx,seq)));
449     BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_ptr_c_d_ctx,seq)));
450     BOOST_TEST(that.unary_c(element1) == fusion::invoke(& members::unary_c, fusion::join(sv_spt_c_d_ctx,seq)));
451 }
452 
453 template <class Sequence>
test_sequence_n(Sequence & seq,mpl::int_<2>)454 void test_sequence_n(Sequence & seq, mpl::int_<2>)
455 {
456     fobj f;
457     BOOST_TEST(f (element1, element2) == fusion::invoke(f , seq));
458     BOOST_TEST(f (element1, const_(element2)) == fusion::invoke(f , const_(seq)));
459     BOOST_TEST(const_(f)(element1, element2) == fusion::invoke<fobj const>(const_(f), seq));
460     BOOST_TEST(const_(f)(element1, const_(element2)) == fusion::invoke<fobj const>(const_(f), const_(seq)));
461 
462     BOOST_TEST(binary1(element1, element2) == fusion::invoke(binary1, seq));
463     BOOST_TEST(binary2(element1, element2) == fusion::invoke(binary2, seq));
464 
465     BOOST_TEST(that.binary(element1,element2) == fusion::invoke(& members::binary, fusion::join(sv_ref_ctx,seq)));
466     BOOST_TEST(that.binary(element1,element2) == fusion::invoke(& members::binary, fusion::join(sv_ptr_ctx,seq)));
467     BOOST_TEST(that.binary(element1,element2) == fusion::invoke(& members::binary, fusion::join(sv_spt_ctx,seq)));
468     BOOST_TEST(that.binary_c(element1,element2) == fusion::invoke(& members::binary_c, fusion::join(sv_obj_ctx,seq)));
469     BOOST_TEST(that.binary_c(element1,element2) == fusion::invoke(& members::binary_c, fusion::join(sv_ref_ctx,seq)));
470     BOOST_TEST(that.binary_c(element1,element2) == fusion::invoke(& members::binary_c, fusion::join(sv_ptr_ctx,seq)));
471     BOOST_TEST(that.binary_c(element1,element2) == fusion::invoke(& members::binary_c, fusion::join(sv_spt_ctx,seq)));
472     BOOST_TEST(that.binary_c(element1,element2) == fusion::invoke(& members::binary_c, fusion::join(sv_obj_c_ctx,seq)));
473     BOOST_TEST(that.binary_c(element1,element2) == fusion::invoke(& members::binary_c, fusion::join(sv_ref_c_ctx,seq)));
474     BOOST_TEST(that.binary_c(element1,element2) == fusion::invoke(& members::binary_c, fusion::join(sv_ptr_c_ctx,seq)));
475     BOOST_TEST(that.binary_c(element1,element2) == fusion::invoke(& members::binary_c, fusion::join(sv_spt_c_ctx,seq)));
476 }
477 
478 template <class Sequence>
test_sequence_n(Sequence & seq,mpl::int_<3>)479 void test_sequence_n(Sequence & seq, mpl::int_<3>)
480 {
481     fobj f;
482 
483     BOOST_TEST(f(element1, element2, element3) == fusion::invoke(f, seq));
484     BOOST_TEST(const_(f)(element1, element2, element3) == fusion::invoke<fobj const>(const_(f), seq));
485 }
486 
487 template <class Sequence>
test_sequence(Sequence & seq)488 void test_sequence(Sequence & seq)
489 {
490     test_sequence_n(seq, mpl::int_<boost::fusion::result_of::size<Sequence>::value>());
491 }
492 
493 
result_type_tests()494 void result_type_tests()
495 {
496     using boost::is_same;
497 
498     BOOST_TEST(( is_same<
499       boost::fusion::result_of::invoke<int (*)(), fusion::vector0<> >::type, int
500     >::value ));
501 // disabled until boost::result_of supports it
502 //    BOOST_TEST(( is_same<
503 //      boost::fusion::result_of::invoke<int (*)(...), fusion::vector1<int> >::type, int
504 //    >::value ));
505     BOOST_TEST(( is_same<
506       boost::fusion::result_of::invoke<int (members::*)(), fusion::vector1<members*> >::type, int
507     >::value ));
508 // disabled until boost::result_of supports it
509 //    BOOST_TEST(( is_same<
510 //      boost::fusion::result_of::invoke<int (members::*)(...), fusion::vector2<members*,int> >::type, int
511 //    >::value ));
512 }
513 
main()514 int main()
515 {
516     result_type_tests();
517 
518     typedef fusion::vector<> vector0;
519     typedef fusion::vector<element1_type> vector1;
520     typedef fusion::vector<element1_type, element2_type> vector2;
521     typedef fusion::vector<element1_type, element2_type, element3_type> vector3;
522 
523     vector0 v0;
524     vector1 v1(element1);
525     vector2 v2(element1, element2);
526 
527 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
528     // Note: C++11 will pickup the rvalue overload for the d argument
529     // since we do not have all permutations (expensive!) for all const&
530     // and && arguments. We either have all && or all const& arguments only.
531     // For that matter, use std::ref to disambiguate the call.
532 
533     vector3 v3(element1, element2, std::ref(element3));
534 #else
535     vector3 v3(element1, element2, element3);
536 #endif
537 
538     test_sequence(v0);
539     test_sequence(v1);
540     test_sequence(v2);
541     test_sequence(v3);
542 
543     typedef fusion::list<> list0;
544     typedef fusion::list<element1_type> list1;
545     typedef fusion::list<element1_type, element2_type> list2;
546     typedef fusion::list<element1_type, element2_type, element3_type> list3;
547 
548     list0 l0;
549     list1 l1(element1);
550     list2 l2(element1, element2);
551     list3 l3(element1, element2, element3);
552 
553     test_sequence(l0);
554     test_sequence(l1);
555     test_sequence(l2);
556     test_sequence(l3);
557 
558     return boost::report_errors();
559 }
560 
561