• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2011 Joel de Guzman
3 
4     Distributed under the Boost Software License, Version 1.0. (See accompanying
5     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7     Problem:
8 
9     So... you have an input sequence I and a target vector R. You want to
10     copy I into R. But, I may have less elements than the result vector R.
11     For those elements not in R, you want them to be default constructed.
12 
13     Here's a case:
14 
15         I: list<double, std::string>
16         R: vector<double, std::string, int, short>
17 
18     You want the elements at the right of I not in R (i.e. int, short)
19     default constructed. Those at the left, found in both I and R, you want
20     to simply copy from I.
21 
22     Of course you want to be able to handle any type of I and R.
23 
24 ==============================================================================*/
25 
26 // We'll use these containers as examples
27 #include <boost/fusion/container/list.hpp>
28 #include <boost/fusion/container/vector.hpp>
29 
30 // For doing I/O
31 #include <boost/fusion/sequence/io.hpp>
32 
33 // We'll use join and advance for processing
34 #include <boost/fusion/algorithm/transformation/join.hpp>
35 #include <boost/fusion/iterator/advance.hpp>
36 
37 // The fusion <--> MPL link header
38 #include <boost/fusion/mpl.hpp>
39 
40 // Same-o same-o
41 #include <iostream>
42 #include <string>
43 
44 int
main()45 main()
46 {
47     using namespace boost::fusion;
48     using namespace boost;
49 
50     // Let's specify our own tuple delimeters for nicer printing
51     std::cout << tuple_open('[');
52     std::cout << tuple_close(']');
53     std::cout << tuple_delimiter(", ");
54 
55     // Here's your input sequence
56     typedef list<double, std::string> I;
57     I i(123.456, "Hello");
58 
59     // Here's your output sequence. For now, it is just a typedef
60     typedef vector<double, std::string, int, short> R;
61 
62     // Let's get the sizes of the sequences. Yeah, you already know that.
63     // But with templates, you are simply given, say, R and I, corresponding
64     // to the types of the sequences. You'll have to deal with it generically.
65     static int const r_size = result_of::size<R>::value;
66     static int const i_size = result_of::size<I>::value;
67 
68     // Make sure that I has no more elements than R
69     // Be nice and catch obvious errors earlier rather than later.
70     // Without this assert, the mistake will still be caught by Fusion,
71     // but the error will point to somewhere really obscure.
72     BOOST_STATIC_ASSERT(i_size <= r_size);
73 
74     // Let's get the begin and end iterator types of the output sequence
75     // There's no actual vector yet. We just want to know the types.
76     typedef result_of::begin<R>::type r_begin;
77     typedef result_of::end<R>::type r_end;
78 
79     // Let's skip i_size elements from r_begin. Again, we just want to know the type.
80     typedef result_of::advance_c<r_begin, i_size>::type r_advance;
81 
82     // Now, make MPL iterators from r_advance and r_end. Ditto, just types.
83     typedef mpl::fusion_iterator<r_advance> mpl_r_advance;
84     typedef mpl::fusion_iterator<r_end> mpl_r_end;
85 
86     // Make an mpl::iterator_range from the MPL iterators we just created
87     // You guessed it! --just a type.
88     typedef mpl::iterator_range<mpl_r_advance, mpl_r_end> tail;
89 
90     // Use join to join the input sequence and our mpl::iterator_range
91     // Our mpl::iterator_range is 'tail'. Here, we'll actually instantiate
92     // 'tail'. Notice that this is a flyweight object, typically just 1 byte
93     // in size -- it doesn't really hold any data, but is a fully conforming
94     // sequence nonetheless. When asked to return its elements, 'tail' returns
95     // each element default constructed. Breeds like a rabbit!
96 
97     // Construct R from the joined sequences:
98     R r(join(i, tail()));
99 
100     // Then finally, print the result:
101     std::cout << r << std::endl;
102 
103     return 0;
104 }
105 
106