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