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_procedure.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/mpl/int.hpp>
22 
23 #include <boost/fusion/container/vector.hpp>
24 #include <boost/fusion/container/list.hpp>
25 #include <boost/fusion/sequence/intrinsic/size.hpp>
26 #include <boost/fusion/sequence/intrinsic/begin.hpp>
27 #include <boost/fusion/view/single_view.hpp>
28 #include <boost/fusion/view/iterator_range.hpp>
29 #include <boost/fusion/iterator/advance.hpp>
30 #include <boost/fusion/algorithm/transformation/join.hpp>
31 
32 #include "../compile_time/sfinae_friendly.hpp"
33 
34 namespace mpl = boost::mpl;
35 namespace fusion = boost::fusion;
36 
37 template <typename T>
const_(T const & t)38 inline T const & const_(T const & t)
39 {
40     return t;
41 }
42 
43 struct object {};
44 struct object_nc : boost::noncopyable {};
45 
46 typedef int         element1_type;
47 typedef object      element2_type;
48 typedef object_nc & element3_type;
49 
50 int         element1 = 100;
51 object      element2 = object();
52 object_nc   element3;
53 
54 class members
55 {
56   public:
57     int data;
58 
members()59     members()
60         : data(20)
61     { }
62 
nullary()63     int nullary() { return element1 = data + 1; }
nullary_c() const64     int nullary_c() const { return element1 = data + 2; }
unary(int & i)65     int unary(int & i) { return i = data + 3; }
unary_c(int & i) const66     int unary_c(int & i) const { return i = data + 4; }
binary(int & i,object)67     int binary(int & i, object) { return i = data + 5; }
binary_c(int & i,object) const68     int binary_c(int & i, object) const { return i = data + 6; }
69 };
70 
71 #ifdef BOOST_NO_CXX11_SMART_PTR
72 typedef std::auto_ptr<members      >       members_ptr;
73 typedef std::auto_ptr<members const> const_members_ptr;
74 #else
75 typedef std::unique_ptr<members      >       members_ptr;
76 typedef std::unique_ptr<members const> const_members_ptr;
77 #endif
78 
79 members that;
80 members_ptr spt_that(new members);
81 const_members_ptr spt_that_c(new members);
82 
83 typedef fusion::single_view<members  > sv_obj;
84 typedef fusion::single_view<members &> sv_ref;
85 typedef fusion::single_view<members *> sv_ptr;
86 typedef fusion::single_view<members const  > sv_obj_c;
87 typedef fusion::single_view<members const &> sv_ref_c;
88 typedef fusion::single_view<members const *> sv_ptr_c;
89 typedef fusion::single_view<members_ptr const &> sv_spt;
90 typedef fusion::single_view<const_members_ptr const &> sv_spt_c;
91 
92 sv_obj sv_obj_ctx(  that);
93 sv_ref sv_ref_ctx(  that);
94 sv_ptr sv_ptr_ctx(& that);
95 sv_obj_c sv_obj_c_ctx(  that);
96 sv_ref_c sv_ref_c_ctx(  that);
97 sv_ptr_c sv_ptr_c_ctx(& that);
98 sv_spt sv_spt_ctx(spt_that);
99 sv_spt_c sv_spt_c_ctx(spt_that_c);
100 template <typename F, typename S>
101 struct sv_helper
102 {
103     SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<F, typename fusion::result_of::join<sv_obj  , S>::type>));
104     SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<F, typename fusion::result_of::join<sv_ref  , S>::type>));
105     SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<F, typename fusion::result_of::join<sv_ptr  , S>::type>));
106     SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<F, typename fusion::result_of::join<sv_obj_c, S>::type>));
107     SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<F, typename fusion::result_of::join<sv_ref_c, S>::type>));
108     SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<F, typename fusion::result_of::join<sv_ptr_c, S>::type>));
109     SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<F, typename fusion::result_of::join<sv_spt  , S>::type>));
110     SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<F, typename fusion::result_of::join<sv_spt_c, S>::type>));
111 };
112 // FIXME:
113 //template struct sv_helper<int (members::*)()      , sfinae_friendly::v1>;
114 //template struct sv_helper<int (members::*)()      , sfinae_friendly::v2>;
115 //template struct sv_helper<int (members::*)()      , sfinae_friendly::v3>;
116 //template struct sv_helper<int (members::*)() const, sfinae_friendly::v1>;
117 //template struct sv_helper<int (members::*)() const, sfinae_friendly::v2>;
118 //template struct sv_helper<int (members::*)() const, sfinae_friendly::v3>;
119 
120 //template struct sv_helper<int (members::*)(int)      , sfinae_friendly::v0>;
121 //template struct sv_helper<int (members::*)(int)      , sfinae_friendly::v1>;
122 //template struct sv_helper<int (members::*)(int)      , sfinae_friendly::v2>;
123 //template struct sv_helper<int (members::*)(int)      , sfinae_friendly::v3>;
124 //template struct sv_helper<int (members::*)(int) const, sfinae_friendly::v0>;
125 //template struct sv_helper<int (members::*)(int) const, sfinae_friendly::v1>;
126 //template struct sv_helper<int (members::*)(int) const, sfinae_friendly::v2>;
127 //template struct sv_helper<int (members::*)(int) const, sfinae_friendly::v3>;
128 
129 //template struct sv_helper<int (members::*)(int, object)      , sfinae_friendly::v0>;
130 //template struct sv_helper<int (members::*)(int, object)      , sfinae_friendly::v1>;
131 //template struct sv_helper<int (members::*)(int, object)      , sfinae_friendly::v2>;
132 //template struct sv_helper<int (members::*)(int, object)      , sfinae_friendly::v3>;
133 //template struct sv_helper<int (members::*)(int, object) const, sfinae_friendly::v0>;
134 //template struct sv_helper<int (members::*)(int, object) const, sfinae_friendly::v1>;
135 //template struct sv_helper<int (members::*)(int, object) const, sfinae_friendly::v2>;
136 //template struct sv_helper<int (members::*)(int, object) const, sfinae_friendly::v3>;
137 
138 struct fobj
139 {
operator ()fobj140     int operator()()       { return element1 = 0; }
operator ()fobj141     int operator()() const { return element1 = 1; }
142 
operator ()fobj143     int operator()(int & i)       { return i = 2 ; }
operator ()fobj144     int operator()(int & i) const { return i = 3; }
145 
operator ()fobj146     int operator()(int & i, object &)             { return i = 4; }
operator ()fobj147     int operator()(int & i, object &) const       { return i = 5; }
operator ()fobj148     int operator()(int & i, object const &)       { return i = 6; }
operator ()fobj149     int operator()(int & i, object const &) const { return i = 7; }
150 
operator ()fobj151     int operator()(int & i, object &, object_nc &)       { return i = 10; }
operator ()fobj152     int operator()(int & i, object &, object_nc &) const { return i = 11; }
153 };
154 // FIXME:
155 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<fobj, sfinae_friendly::v0>));
156 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<fobj, sfinae_friendly::v1>));
157 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<fobj, sfinae_friendly::v2>));
158 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<fobj, sfinae_friendly::v3>));
159 
160 struct fobj_nc
161       : boost::noncopyable
162 {
operator ()fobj_nc163     int operator()()       { return element1 = 12; }
operator ()fobj_nc164     int operator()() const { return element1 = 13; }
165 
operator ()fobj_nc166     int operator()(int & i)       { return i = 14; }
operator ()fobj_nc167     int operator()(int & i) const { return i = 15; }
168 };
169 // FIXME:
170 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<fobj_nc, sfinae_friendly::v0>));
171 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<fobj_nc, sfinae_friendly::v1>));
172 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<fobj_nc, sfinae_friendly::v2>));
173 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<fobj_nc, sfinae_friendly::v3>));
174 
nullary()175 int nullary() { return element1 = 16; }
unary(int & i)176 int unary(int & i) { return  i = 17; }
binary1(int & i,object &)177 int binary1(int & i, object &) { return i = 18; }
binary2(int & i,object const &)178 int binary2(int & i, object const &) { return i = 19; }
179 //FIXME
180 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<int(*)(), sfinae_friendly::v1>));
181 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<int(*)(), sfinae_friendly::v2>));
182 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<int(*)(), sfinae_friendly::v3>));
183 //
184 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<int(*)(int), sfinae_friendly::v0>));
185 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<int(*)(int), sfinae_friendly::v1>));
186 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<int(*)(int), sfinae_friendly::v2>));
187 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<int(*)(int), sfinae_friendly::v3>));
188 //
189 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<int(*)(int, object &), sfinae_friendly::v0>));
190 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<int(*)(int, object &), sfinae_friendly::v1>));
191 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<int(*)(int, object &), sfinae_friendly::v2>));
192 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<int(*)(int, object &), sfinae_friendly::v3>));
193 //
194 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<int(*)(int, object const &), sfinae_friendly::v0>));
195 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<int(*)(int, object const &), sfinae_friendly::v1>));
196 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<int(*)(int, object const &), sfinae_friendly::v2>));
197 //SFINAE_FRIENDLY_ASSERT((fusion::result_of::invoke_procedure<int(*)(int, object const &), sfinae_friendly::v3>));
198 
199 typedef int (*                   func_ptr)(int &);
200 typedef int (* const           c_func_ptr)(int &);
201 typedef int (* volatile        v_func_ptr)(int &);
202 typedef int (* const volatile cv_func_ptr)(int &);
203 
204    func_ptr func_ptr1 = &unary;
205  c_func_ptr func_ptr2 = &unary;
206  v_func_ptr func_ptr3 = &unary;
207 cv_func_ptr func_ptr4 = &unary;
208 
209 
210 
211 #define COMPARE_EFFECT(e,t)               \
212     {                                      \
213         element1 = 1234567; e;             \
214         int expected = element1;           \
215         element1 = 1234567; t;             \
216         BOOST_TEST(expected == element1 ); \
217     }
218 
219 
220 template <class Sequence>
test_sequence_n(Sequence & seq,mpl::int_<0>)221 void test_sequence_n(Sequence & seq, mpl::int_<0>)
222 {
223     // Function Objects
224 
225     fobj f;
226 
227     COMPARE_EFFECT(f (), fusion::invoke_procedure(f ,        seq ));
228     COMPARE_EFFECT(f (), fusion::invoke_procedure(f , const_(seq)));
229 
230     // Note: The function object is taken by value, so we request the copy
231     // to be const with an explicit template argument. We can also request
232     // the function object to be pased by reference...
233     COMPARE_EFFECT(const_(f)(), fusion::invoke_procedure<fobj const  >(const_(f),        seq ));
234     COMPARE_EFFECT(const_(f)(), fusion::invoke_procedure<fobj const &>(const_(f), const_(seq)));
235 
236     fobj_nc nc_f;
237     // ...and we further ensure there is no copying in this case, using a
238     // noncopyable function object.
239     COMPARE_EFFECT(nc_f (), fusion::invoke_procedure<fobj_nc &>(nc_f ,        seq ));
240     COMPARE_EFFECT(nc_f (), fusion::invoke_procedure<fobj_nc &>(nc_f , const_(seq)));
241     COMPARE_EFFECT(const_(nc_f)(), fusion::invoke_procedure<fobj_nc const &>(const_(nc_f),        seq ));
242     COMPARE_EFFECT(const_(nc_f)(), fusion::invoke_procedure<fobj_nc const &>(const_(nc_f), const_(seq)));
243 
244     // Builtin Functions
245 
246     // Call through ref/ptr to function
247     COMPARE_EFFECT(nullary(), fusion::invoke_procedure<int (&)()>(nullary, seq));
248     COMPARE_EFFECT(nullary(), fusion::invoke_procedure(& nullary, seq));
249 
250     // Call through ptr to member function
251     // Note: The non-const function members::nullary can't be invoked with
252     // fusion::join(sv_obj_ctx,seq)), which is const and so is its first element
253     COMPARE_EFFECT(that.nullary(), fusion::invoke_procedure(& members::nullary, fusion::join(sv_ref_ctx,seq)));
254     COMPARE_EFFECT(that.nullary(), fusion::invoke_procedure(& members::nullary, fusion::join(sv_ptr_ctx,seq)));
255     COMPARE_EFFECT(that.nullary(), fusion::invoke_procedure(& members::nullary, fusion::join(sv_spt_ctx,seq)));
256     COMPARE_EFFECT(that.nullary_c(), fusion::invoke_procedure(& members::nullary_c, fusion::join(sv_obj_ctx,seq)));
257     COMPARE_EFFECT(that.nullary_c(), fusion::invoke_procedure(& members::nullary_c, fusion::join(sv_ref_ctx,seq)));
258     COMPARE_EFFECT(that.nullary_c(), fusion::invoke_procedure(& members::nullary_c, fusion::join(sv_ptr_ctx,seq)));
259     COMPARE_EFFECT(that.nullary_c(), fusion::invoke_procedure(& members::nullary_c, fusion::join(sv_spt_ctx,seq)));
260     COMPARE_EFFECT(that.nullary_c(), fusion::invoke_procedure(& members::nullary_c, fusion::join(sv_obj_c_ctx,seq)));
261     COMPARE_EFFECT(that.nullary_c(), fusion::invoke_procedure(& members::nullary_c, fusion::join(sv_ref_c_ctx,seq)));
262     COMPARE_EFFECT(that.nullary_c(), fusion::invoke_procedure(& members::nullary_c, fusion::join(sv_ptr_c_ctx,seq)));
263     COMPARE_EFFECT(that.nullary_c(), fusion::invoke_procedure(& members::nullary_c, fusion::join(sv_spt_c_ctx,seq)));
264 }
265 
266 template <class Sequence>
test_sequence_n(Sequence & seq,mpl::int_<1>)267 void test_sequence_n(Sequence & seq, mpl::int_<1>)
268 {
269     fobj f;
270     COMPARE_EFFECT(f(element1), fusion::invoke_procedure(f , seq ));
271     COMPARE_EFFECT(f(element1), fusion::invoke_procedure(f , const_(seq)));
272     COMPARE_EFFECT(const_(f)(element1), fusion::invoke_procedure<fobj const  >(const_(f), seq ));
273     COMPARE_EFFECT(const_(f)(element1), fusion::invoke_procedure<fobj const &>(const_(f), const_(seq)));
274 
275     fobj_nc nc_f;
276     COMPARE_EFFECT(nc_f(element1), fusion::invoke_procedure<fobj_nc &>(nc_f, seq ));
277     COMPARE_EFFECT(nc_f(element1), fusion::invoke_procedure<fobj_nc &>(nc_f, const_(seq)));
278     COMPARE_EFFECT(const_(nc_f)(element1), fusion::invoke_procedure<fobj_nc const &>(const_(nc_f), seq ));
279     COMPARE_EFFECT(const_(nc_f)(element1), fusion::invoke_procedure<fobj_nc const &>(const_(nc_f), const_(seq)));
280 
281     COMPARE_EFFECT(unary(element1), fusion::invoke_procedure<int (&)(int &)>(unary, seq));
282     COMPARE_EFFECT(func_ptr1(element1), fusion::invoke_procedure(func_ptr1, seq));
283     COMPARE_EFFECT(func_ptr2(element1), fusion::invoke_procedure(func_ptr2, seq));
284     COMPARE_EFFECT(func_ptr3(element1), fusion::invoke_procedure(func_ptr3, seq));
285     COMPARE_EFFECT(func_ptr4(element1), fusion::invoke_procedure(func_ptr4, seq));
286 
287     COMPARE_EFFECT(that.unary(element1), fusion::invoke_procedure(& members::unary, fusion::join(sv_ref_ctx,seq)));
288     COMPARE_EFFECT(that.unary(element1), fusion::invoke_procedure(& members::unary, fusion::join(sv_ptr_ctx,seq)));
289     COMPARE_EFFECT(that.unary(element1), fusion::invoke_procedure(& members::unary, fusion::join(sv_spt_ctx,seq)));
290     COMPARE_EFFECT(that.unary_c(element1), fusion::invoke_procedure(& members::unary_c, fusion::join(sv_obj_ctx,seq)));
291     COMPARE_EFFECT(that.unary_c(element1), fusion::invoke_procedure(& members::unary_c, fusion::join(sv_ref_ctx,seq)));
292     COMPARE_EFFECT(that.unary_c(element1), fusion::invoke_procedure(& members::unary_c, fusion::join(sv_ptr_ctx,seq)));
293     COMPARE_EFFECT(that.unary_c(element1), fusion::invoke_procedure(& members::unary_c, fusion::join(sv_spt_ctx,seq)));
294     COMPARE_EFFECT(that.unary_c(element1), fusion::invoke_procedure(& members::unary_c, fusion::join(sv_obj_c_ctx,seq)));
295     COMPARE_EFFECT(that.unary_c(element1), fusion::invoke_procedure(& members::unary_c, fusion::join(sv_ref_c_ctx,seq)));
296     COMPARE_EFFECT(that.unary_c(element1), fusion::invoke_procedure(& members::unary_c, fusion::join(sv_ptr_c_ctx,seq)));
297     COMPARE_EFFECT(that.unary_c(element1), fusion::invoke_procedure(& members::unary_c, fusion::join(sv_spt_c_ctx,seq)));
298 }
299 
300 template <class Sequence>
test_sequence_n(Sequence & seq,mpl::int_<2>)301 void test_sequence_n(Sequence & seq, mpl::int_<2>)
302 {
303     fobj f;
304     COMPARE_EFFECT(f (element1, element2), fusion::invoke_procedure(f , seq));
305     COMPARE_EFFECT(f (element1, const_(element2)), fusion::invoke_procedure(f , const_(seq)));
306     COMPARE_EFFECT(const_(f)(element1, element2), fusion::invoke_procedure<fobj const>(const_(f), seq));
307     COMPARE_EFFECT(const_(f)(element1, const_(element2)), fusion::invoke_procedure<fobj const>(const_(f), const_(seq)));
308 
309     COMPARE_EFFECT(binary1(element1, element2), fusion::invoke_procedure(binary1, seq));
310     COMPARE_EFFECT(binary2(element1, element2), fusion::invoke_procedure(binary2, seq));
311 
312     COMPARE_EFFECT(that.binary(element1,element2), fusion::invoke_procedure(& members::binary, fusion::join(sv_ref_ctx,seq)));
313     COMPARE_EFFECT(that.binary(element1,element2), fusion::invoke_procedure(& members::binary, fusion::join(sv_ptr_ctx,seq)));
314     COMPARE_EFFECT(that.binary(element1,element2), fusion::invoke_procedure(& members::binary, fusion::join(sv_spt_ctx,seq)));
315     COMPARE_EFFECT(that.binary_c(element1,element2), fusion::invoke_procedure(& members::binary_c, fusion::join(sv_obj_ctx,seq)));
316     COMPARE_EFFECT(that.binary_c(element1,element2), fusion::invoke_procedure(& members::binary_c, fusion::join(sv_ref_ctx,seq)));
317     COMPARE_EFFECT(that.binary_c(element1,element2), fusion::invoke_procedure(& members::binary_c, fusion::join(sv_ptr_ctx,seq)));
318     COMPARE_EFFECT(that.binary_c(element1,element2), fusion::invoke_procedure(& members::binary_c, fusion::join(sv_spt_ctx,seq)));
319     COMPARE_EFFECT(that.binary_c(element1,element2), fusion::invoke_procedure(& members::binary_c, fusion::join(sv_obj_c_ctx,seq)));
320     COMPARE_EFFECT(that.binary_c(element1,element2), fusion::invoke_procedure(& members::binary_c, fusion::join(sv_ref_c_ctx,seq)));
321     COMPARE_EFFECT(that.binary_c(element1,element2), fusion::invoke_procedure(& members::binary_c, fusion::join(sv_ptr_c_ctx,seq)));
322     COMPARE_EFFECT(that.binary_c(element1,element2), fusion::invoke_procedure(& members::binary_c, fusion::join(sv_spt_c_ctx,seq)));
323 }
324 
325 template <class Sequence>
test_sequence_n(Sequence & seq,mpl::int_<3>)326 void test_sequence_n(Sequence & seq, mpl::int_<3>)
327 {
328     fobj f;
329 
330     COMPARE_EFFECT(f(element1, element2, element3), fusion::invoke_procedure(f, seq));
331     COMPARE_EFFECT(const_(f)(element1, element2, element3), fusion::invoke_procedure<fobj const>(const_(f), seq));
332 }
333 
334 template <class Sequence>
test_sequence(Sequence & seq)335 void test_sequence(Sequence & seq)
336 {
337     test_sequence_n(seq, mpl::int_<boost::fusion::result_of::size<Sequence>::value>());
338 }
339 
main()340 int main()
341 {
342     typedef fusion::vector<> vector0;
343     typedef fusion::vector<element1_type &> vector1;
344     typedef fusion::vector<element1_type &, element2_type> vector2;
345     typedef fusion::vector<element1_type &, element2_type, element3_type> vector3;
346 
347     vector0 v0;
348     vector1 v1(element1);
349 
350 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
351     // Note: C++11 will pickup the rvalue overload for the d argument
352     // since we do not have all permutations (expensive!) for all const&
353     // and && arguments. We either have all && or all const& arguments only.
354     // For that matter, use std::ref to disambiguate the call.
355 
356     vector2 v2(std::ref(element1), element2);
357     vector3 v3(std::ref(element1), element2, std::ref(element3));
358 #else
359     vector2 v2(element1, element2);
360     vector3 v3(element1, element2, element3);
361 #endif
362 
363     test_sequence(v0);
364     test_sequence(v1);
365     test_sequence(v2);
366     test_sequence(v3);
367 
368     typedef fusion::list<> list0;
369     typedef fusion::list<element1_type &> list1;
370     typedef fusion::list<element1_type &, element2_type> list2;
371     typedef fusion::list<element1_type &, element2_type, element3_type> list3;
372 
373     list0 l0;
374     list1 l1(element1);
375     list2 l2(element1, element2);
376     list3 l3(element1, element2, element3);
377 
378     test_sequence(l0);
379     test_sequence(l1);
380     test_sequence(l2);
381     test_sequence(l3);
382 
383     return boost::report_errors();
384 }
385 
386