• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
3     Copyright (c) 2011 Nathan Ridge
4     Copyright (c) 2006 Dan Marsden
5 
6     Distributed under the Boost Software License, Version 1.0. (See accompanying
7     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 ==============================================================================*/
9 
10 /*=============================================================================
11     An implementation of a std::pair like triple<T0, T1, T2>
12     We use fusion::sequence_facade and fusion::iterator_facade
13     to make our triple a fully conforming Boost.Fusion random
14     traversal sequence.
15 ==============================================================================*/
16 
17 #include <boost/detail/lightweight_test.hpp>
18 
19 #include <boost/fusion/sequence/sequence_facade.hpp>
20 #include <boost/fusion/iterator/iterator_facade.hpp>
21 #include <boost/fusion/sequence/intrinsic.hpp>
22 #include <boost/fusion/iterator.hpp>
23 #include <boost/fusion/support/category_of.hpp>
24 #include <boost/fusion/algorithm/iteration/fold.hpp>
25 
26 #include <boost/mpl/int.hpp>
27 #include <boost/mpl/identity.hpp>
28 #include <boost/mpl/minus.hpp>
29 #include <boost/mpl/assert.hpp>
30 
31 #include <boost/type_traits/is_const.hpp>
32 #include <boost/type_traits/is_same.hpp>
33 
34 #include <string>
35 
36 namespace mpl = boost::mpl;
37 namespace fusion = boost::fusion;
38 
39 namespace demo
40 {
41     template<typename Seq, int N>
42     struct triple_iterator
43         : fusion::iterator_facade<triple_iterator<Seq, N>,
44           fusion::random_access_traversal_tag>
45     {
46         typedef mpl::int_<N> index;
47         typedef Seq sequence_type;
48 
triple_iteratordemo::triple_iterator49         triple_iterator(Seq& seq)
50             : seq_(seq) {}
51 
52         Seq& seq_;
53 
54         template<typename T>
55         struct value_of;
56 
57         template<typename Sq>
58         struct value_of<triple_iterator<Sq, 0> >
59             : mpl::identity<typename Sq::t0_type>
60         {};
61 
62         template<typename Sq>
63         struct value_of<triple_iterator<Sq, 1> >
64             : mpl::identity<typename Sq::t1_type>
65         {};
66 
67         template<typename Sq>
68         struct value_of<triple_iterator<Sq, 2> >
69             : mpl::identity<typename Sq::t2_type>
70         {};
71 
72         template<typename T>
73         struct deref;
74 
75         template <typename Sq>
76         struct deref<triple_iterator<Sq, 0> >
77         {
78             typedef typename Sq::t0_type& type;
79 
80             static type
calldemo::triple_iterator::deref81             call(triple_iterator<Sq, 0> const& iter)
82             {
83                 return iter.seq_.t0;
84             }
85         };
86 
87         template <typename Sq>
88         struct deref<triple_iterator<Sq, 0> const>
89         {
90             typedef typename Sq::t0_type const& type;
91 
92             static type
calldemo::triple_iterator::deref93             call(triple_iterator<Sq, 0> const& iter)
94             {
95                 return iter.seq_.t0;
96             }
97         };
98 
99         template <typename Sq>
100         struct deref<triple_iterator<Sq, 1> >
101         {
102             typedef typename Sq::t1_type& type;
103 
104             static type
calldemo::triple_iterator::deref105             call(triple_iterator<Sq, 1> const& iter)
106             {
107                 return iter.seq_.t1;
108             }
109         };
110 
111         template <typename Sq>
112         struct deref<triple_iterator<Sq, 1> const>
113         {
114             typedef typename Sq::t1_type const& type;
115 
116             static type
calldemo::triple_iterator::deref117             call(triple_iterator<Sq, 1> const& iter)
118             {
119                 return iter.seq_.t1;
120             }
121         };
122 
123         template <typename Sq>
124         struct deref<triple_iterator<Sq, 2> >
125         {
126             typedef typename Sq::t2_type& type;
127 
128             static type
calldemo::triple_iterator::deref129             call(triple_iterator<Sq, 2> const& iter)
130             {
131                 return iter.seq_.t2;
132             }
133         };
134 
135         template <typename Sq>
136         struct deref<triple_iterator<Sq, 2> const>
137         {
138             typedef typename Sq::t2_type const& type;
139 
140             static type
calldemo::triple_iterator::deref141             call(triple_iterator<Sq, 2> const& iter)
142             {
143                 return iter.seq_.t2;
144             }
145         };
146 
147         template<typename It>
148         struct next
149         {
150             typedef triple_iterator<
151                 typename It::sequence_type, It::index::value + 1>
152             type;
153 
calldemo::triple_iterator::next154             static type call(It const& it)
155             {
156                 return type(it.seq_);
157             }
158         };
159 
160         template<typename It>
161         struct prior
162         {
163             typedef triple_iterator<
164                 typename It::sequence_type, It::index::value - 1>
165             type;
166 
calldemo::triple_iterator::prior167             static type call(It const& it)
168             {
169                 return type(it.seq_);
170             }
171         };
172 
173         template<typename It1, typename It2>
174         struct distance
175         {
176             typedef typename mpl::minus<
177               typename It2::index, typename It1::index>::type
178             type;
179 
calldemo::triple_iterator::distance180             static type call(It1 const& it1, It2 const& it2)
181             {
182                 return type();
183             }
184         };
185 
186         template<typename It, typename M>
187         struct advance
188         {
189             typedef triple_iterator<
190                 typename It::sequence_type,
191                 It::index::value + M::value>
192             type;
193 
calldemo::triple_iterator::advance194             static type call(It const& it)
195             {
196                 return type(it.seq_);
197             }
198         };
199     };
200 
201     template<typename T0, typename T1, typename T2>
202     struct triple
203         : fusion::sequence_facade<triple<T0, T1, T2>,
204           fusion::random_access_traversal_tag>
205     {
tripledemo::triple206         triple(T0 const& t0, T1 const& t1, T2 const& t2)
207             : t0(t0), t1(t1), t2(t2)
208         {}
209 
210         template<typename Sq>
211         struct begin
212         {
213             typedef demo::triple_iterator<Sq, 0> type;
214 
calldemo::triple::begin215             static type call(Sq& sq)
216             {
217                 return type(sq);
218             }
219         };
220 
221         template<typename Sq>
222         struct end
223         {
224             typedef demo::triple_iterator<Sq, 3> type;
225 
calldemo::triple::end226             static type call(Sq& sq)
227             {
228                 return type(sq);
229             }
230         };
231 
232         template<typename Sq>
233         struct size
234             : mpl::int_<3>
235         {};
236 
237         template<typename Sq, typename N>
238         struct value_at
239             : value_at<Sq, mpl::int_<N::value> >
240         {};
241 
242         template<typename Sq>
243         struct value_at<Sq, mpl::int_<0> >
244         {
245             typedef typename Sq::t0_type type;
246         };
247 
248         template<typename Sq>
249         struct value_at<Sq, mpl::int_<1> >
250         {
251             typedef typename Sq::t1_type type;
252         };
253 
254         template<typename Sq>
255         struct value_at<Sq, mpl::int_<2> >
256         {
257             typedef typename Sq::t2_type type;
258         };
259 
260         template<typename Sq, typename N>
261         struct at
262             : at<Sq, mpl::int_<N::value> >
263         {};
264 
265         template<typename Sq>
266         struct at<Sq, mpl::int_<0> >
267         {
268             typedef typename
269                 mpl::if_<
270                     boost::is_const<Sq>
271                   , typename Sq::t0_type const&
272                   , typename Sq::t0_type&
273                 >::type
274             type;
275 
calldemo::triple::at276             static type call(Sq& sq)
277             {
278                 return sq.t0;
279             }
280         };
281 
282         template<typename Sq>
283         struct at<Sq, mpl::int_<1> >
284         {
285             typedef typename
286                 mpl::if_<
287                     boost::is_const<Sq>
288                   , typename Sq::t1_type const&
289                   , typename Sq::t1_type&
290                 >::type
291             type;
292 
calldemo::triple::at293             static type call(Sq& sq)
294             {
295                 return sq.t1;
296             }
297         };
298 
299         template<typename Sq>
300         struct at<Sq, mpl::int_<2> >
301         {
302             typedef typename
303                 mpl::if_<
304                     boost::is_const<Sq>
305                   , typename Sq::t2_type const&
306                   , typename Sq::t2_type&
307                 >::type
308             type;
309 
calldemo::triple::at310             static type call(Sq& sq)
311             {
312                 return sq.t2;
313             }
314         };
315 
316         typedef T0 t0_type;
317         typedef T1 t1_type;
318         typedef T2 t2_type;
319 
320         T0 t0;
321         T1 t1;
322         T2 t2;
323     };
324 }
325 
326 struct modifying_fold_functor
327 {
328     template <typename T>
329     struct result
330     {
331         typedef bool type;
332     };
333 
334     template <typename T>
operator ()modifying_fold_functor335     bool operator()(bool b, T&)
336     {
337         return b;
338     }
339 };
340 
341 struct nonmodifying_fold_functor
342 {
343     template <typename T>
344     struct result
345     {
346         typedef bool type;
347     };
348 
349     template <typename T>
operator ()nonmodifying_fold_functor350     bool operator()(bool b, const T&)
351     {
352         return b;
353     }
354 };
355 
main()356 int main()
357 {
358     typedef demo::triple<int, char, std::string> my_triple;
359     my_triple t(101, 'a', "hello");
360     BOOST_TEST(*fusion::begin(t) == 101);
361     BOOST_TEST(*fusion::next(fusion::begin(t)) == 'a');
362     BOOST_TEST(*fusion::prior(fusion::end(t)) == "hello");
363     BOOST_TEST(fusion::distance(fusion::begin(t), fusion::end(t)) == 3);
364     BOOST_TEST(fusion::size(t) == 3);
365     BOOST_MPL_ASSERT((boost::is_same<
366         int, fusion::result_of::value_at_c<my_triple, 0>::type>));
367     BOOST_MPL_ASSERT((boost::is_same<
368       char, fusion::result_of::value_at_c<my_triple, 1>::type>));
369     BOOST_MPL_ASSERT((boost::is_same<
370         std::string, fusion::result_of::value_at_c<my_triple, 2>::type>));
371     BOOST_TEST(fusion::at_c<0>(t) == 101);
372     BOOST_TEST(fusion::at_c<1>(t) == 'a');
373     BOOST_TEST(fusion::at_c<2>(t) == "hello");
374     BOOST_TEST(fusion::fold(t, true, modifying_fold_functor()) == true);
375     BOOST_TEST(fusion::fold(t, true, nonmodifying_fold_functor()) == true);
376     return boost::report_errors();
377 }
378