1[/==============================================================================
2    Copyright (C) 2001-2011 Joel de Guzman
3    Copyright (C) 2006 Dan Marsden
4
5    Use, modification and distribution is 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[section Extension]
10
11[section:ext_full The Full Extension Mechanism]
12
13The Fusion library is designed to be extensible, new sequences types can easily
14be added. In fact, the library support for `std::pair`, `boost::array` and __mpl__
15sequences is entirely provided using the extension mechanism.
16
17The process for adding a new sequence type to Fusion is:
18
19# Enable the __tag_dispatching__ mechanism used by Fusion for your sequence type
20# Design an iterator type for the sequence
21# Provide specialized behaviour for the intrinsic operations of the new Fusion sequence
22
23[heading Our example]
24
25In order to illustrate enabling a new sequence type for use with Fusion, we
26are going to use the type:
27
28    namespace example
29    {
30        struct example_struct
31        {
32            std::string name;
33            int age;
34            example_struct(
35                const std::string& n,
36                int a)
37                : name(n), age(a)
38            {}
39        };
40    }
41
42We are going to pretend that this type has been provided by a 3rd party
43library, and therefore cannot be modified. We shall work through all the
44necessary steps to enable `example_struct` to serve as an __associative_sequence__
45as described in the __quick_start__ guide.
46
47[heading Enabling Tag Dispatching]
48
49The Fusion extensibility mechanism uses __tag_dispatching__ to call the
50correct code for a given sequence type. In order to exploit the tag
51dispatching mechanism we must first declare a new tag type for the
52mechanism to use. For example:
53
54    namespace example {
55        struct example_sequence_tag; // Only definition needed
56    }
57
58Next we need to enable the `traits::tag_of` metafunction to return our newly chosen
59tag type for operations involving our sequence. This is done by specializing
60`traits::tag_of` for our sequence type.
61
62    #include <boost/fusion/support/tag_of_fwd.hpp>
63    #include <boost/fusion/include/tag_of_fwd.hpp>
64
65    namespace boost { namespace fusion { namespace traits {
66        template<>
67        struct tag_of<example_struct>
68        {
69            typedef example::example_sequence_tag type;
70        };
71    }}}
72
73`traits::tag_of` also has a second template argument,
74that can be used in conjunction with `boost::enable_if` to provide tag
75support for groups of related types. This feature is not necessary
76for our sequence, but for an example see the code in:
77
78    #include <boost/fusion/adapted/array/tag_of.hpp>
79    #include <boost/fusion/include/tag_of.hpp>
80
81[heading Designing a suitable iterator]
82
83We need an iterator to describe positions, and provide access to
84the data within our sequence. As it is straightforward to do,
85we are going to provide a random access iterator in our example.
86
87We will use a simple design, in which the 2 members of
88`example_struct` are given numbered indices, 0 for `name` and
891 for `age` respectively.
90
91    template<typename Struct, int Pos>
92    struct example_struct_iterator
93        : boost::fusion::iterator_base<example_struct_iterator<Struct, Pos> >
94    {
95        BOOST_STATIC_ASSERT(Pos >=0 && Pos < 3);
96        typedef Struct struct_type;
97        typedef boost::mpl::int_<Pos> index;
98        typedef boost::fusion::random_access_traversal_tag category;
99
100        example_struct_iterator(Struct& str)
101            : struct_(str) {}
102
103        Struct& struct_;
104    };
105
106A quick summary of the details of our iterator:
107
108# The iterator is parameterized by the type it is iterating over, and the index of the current element.
109# The typedefs `struct_type` and `index` provide convenient access to information we will need later in
110  the implementation.
111# The typedef `category` allows the `traits::__category_of__` metafunction to establish
112  the traversal category of the iterator.
113# The constructor stores a reference to the `example_struct` being iterated over.
114
115We also need to enable __tag_dispatching__ for our iterator type, with another specialization of
116`traits::tag_of`.
117
118In isolation, the iterator implementation is pretty dry. Things should become clearer as we
119add features to our implementation.
120
121[heading A first couple of instructive features]
122
123To start with, we will get the __result_of_value_of__ metafunction working. To
124do this, we provide a specialization of the `boost::fusion::extension::value_of_impl` template for
125our iterator's tag type.
126
127    template<>
128    struct value_of_impl<example::example_struct_iterator_tag>
129    {
130        template<typename Iterator>
131        struct apply;
132
133        template<typename Struct>
134        struct apply<example::example_struct_iterator<Struct, 0> >
135        {
136            typedef std::string type;
137        };
138
139        template<typename Struct>
140        struct apply<example::example_struct_iterator<Struct, 1> >
141        {
142            typedef int type;
143        };
144    };
145
146The implementation itself is pretty simple, it just uses 2 partial specializations to
147provide the type of the 2 different members of `example_struct`, based on the index of the iterator.
148
149To understand how `value_of_impl` is used by the library we will look at the implementation of __result_of_value_of__:
150
151    template <typename Iterator>
152    struct value_of
153        : extension::value_of_impl<typename detail::tag_of<Iterator>::type>::
154            template apply<Iterator>
155    {};
156
157So __result_of_value_of__ uses __tag_dispatching__ to select an __mpl_metafunction_class__
158to provide its functionality. You will notice this pattern throughout the
159implementation of Fusion.
160
161Ok, lets enable dereferencing of our iterator. In this case we must provide a suitable
162specialization of `deref_impl`.
163
164    template<>
165    struct deref_impl<example::example_struct_iterator_tag>
166    {
167        template<typename Iterator>
168        struct apply;
169
170        template<typename Struct>
171        struct apply<example::example_struct_iterator<Struct, 0> >
172        {
173            typedef typename mpl::if_<
174                is_const<Struct>, std::string const&, std::string&>::type type;
175
176            static type
177            call(example::example_struct_iterator<Struct, 0> const& it)
178            {
179                return it.struct_.name;
180            }
181        };
182
183        template<typename Struct>
184        struct apply<example::example_struct_iterator<Struct, 1> >
185        {
186            typedef typename mpl::if_<
187                is_const<Struct>, int const&, int&>::type type;
188
189            static type
190            call(example::example_struct_iterator<Struct, 1> const& it)
191            {
192                    return it.struct_.age;
193                }
194            };
195        };
196    }
197
198The use of `deref_impl` is very similar to that of `value_of_impl`, but it also
199provides some runtime functionality this time via the `call` static member function.
200To see how `deref_impl` is used, lets have a look at the implementation of __deref__:
201
202    namespace result_of
203    {
204        template <typename Iterator>
205        struct __deref__
206            : extension::deref_impl<typename detail::tag_of<Iterator>::type>::
207                template apply<Iterator>
208        {};
209    }
210
211    template <typename Iterator>
212    typename result_of::deref<Iterator>::type
213    __deref__(Iterator const& i)
214    {
215        typedef result_of::deref<Iterator> deref_meta;
216        return deref_meta::call(i);
217    }
218
219So again __result_of_deref__ uses __tag_dispatching__ in exactly the
220same way as the __result_of_value_of__ implementation. The runtime functionality used
221by __deref__ is provided by the `call` static function of the selected
222__mpl_metafunction_class__.
223
224The actual implementation of `deref_impl` is slightly more complex than that of  `value_of_impl`.
225We also need to implement the `call` function, which returns a reference
226to the appropriate member of the underlying sequence. We also require a little
227bit of metaprogramming to return `const` references if the underlying sequence
228is const.
229
230[note Although there is a fair amount of left to do to produce a fully fledged
231Fusion sequence, __result_of_value_of__ and __deref__ illustrate all the significant concepts
232required. The remainder of the process is very repetitive, simply requiring
233implementation of a suitable `xxxx_impl` for each feature `xxxx`.
234]
235
236[heading Implementing the remaining iterator functionality]
237
238Ok, now we have seen the way __result_of_value_of__ and __deref__ work, everything else will work
239 in pretty much the same way. Lets start with forward iteration,
240by providing a `next_impl`:
241
242    template<>
243    struct next_impl<example::example_struct_iterator_tag>
244    {
245        template<typename Iterator>
246        struct apply
247        {
248            typedef typename Iterator::struct_type struct_type;
249            typedef typename Iterator::index index;
250            typedef example::example_struct_iterator<struct_type, index::value + 1> type;
251
252            static type
253            call(Iterator const& i)
254            {
255                 return type(i.struct_);
256            }
257        };
258    };
259
260This should be very familiar from our `deref_impl` implementation, we will be
261using this approach again and again now. Our design is simply to increment
262the `index` counter to move on to the next element. The various other iterator
263manipulations we need to perform will all just involve simple calculations
264with the `index` variables.
265
266We also need to provide a suitable `equal_to_impl` so that iterators can be
267correctly compared. A __bidirectional_iterator__ will also need an implementation of `prior_impl`. For a
268__random_access_iterator__ `distance_impl` and `advance_impl` also need to be provided
269in order to satisfy the necessary complexity guarantees. As our iterator is
270a __random_access_iterator__ we will have to implement all of these functions.
271
272Full implementations of `prior_impl`, `advance_impl`, `distance_impl` and `equal_to_impl` are
273provided in the example code.
274
275[heading Implementing the intrinsic functions of the sequence]
276
277In order that Fusion can correctly identify our sequence as a Fusion sequence, we
278need to enable `is_sequence` for our sequence type. As usual we just create
279an `impl` type specialized for our sequence tag:
280
281     template<>
282     struct is_sequence_impl<example::example_sequence_tag>
283     {
284         template<typename T>
285         struct apply : mpl::true_ {};
286     };
287
288We've some similar formalities to complete, providing `category_of_impl` so Fusion
289can correctly identify our sequence type, and `is_view_impl` so Fusion can correctly
290identify our sequence as not being a __view__ type. Implementations are
291provide in the example code.
292
293Now we've completed some formalities, on to more interesting features. Lets get
294__begin__ working so that we can get an iterator to start accessing the data in
295our sequence.
296
297    template<>
298    struct begin_impl<example::example_sequence_tag>
299    {
300        template<typename Sequence>
301        struct apply
302        {
303            typedef example::example_struct_iterator<Sequence, 0> type;
304
305            static type
306            call(Sequence& seq)
307            {
308                return type(seq);
309            }
310        };
311    };
312
313The implementation uses the same ideas we have applied throughout, in this case
314we are just creating one of the iterators we developed earlier, pointing to the
315first element in the sequence. The implementation of __end__ is very similar, and
316is provided in the example code.
317
318For our __random_access_sequence__ we will also need to implement `size_impl`,
319`value_at_impl` and `at_impl`.
320
321[heading Enabling our type as an associative sequence]
322
323In order for `example_struct` to serve as an associative forward sequence,
324we need to adapt the traversal category of our sequence and our iterator
325accordingly and enable 3 intrinsic sequence lookup features, __at_key__,
326__result_of_value_at_key__ and __has_key__. We also need to enable 3 iterator lookup
327features, __result_of_key_of__, __result_of_value_of_data__ and __deref_data__.
328
329To implement `at_key_impl` we need to associate the `fields::name` and `fields::age`
330types described in the __quick_start__ guide with the appropriate members of `example_struct`.
331Our implementation is as follows:
332
333    template<>
334    struct at_key_impl<example::example_sequence_tag>
335    {
336        template<typename Sequence, typename Key>
337        struct apply;
338
339        template<typename Sequence>
340        struct apply<Sequence, fields::name>
341        {
342            typedef typename mpl::if_<
343                is_const<Sequence>,
344                std::string const&,
345                std::string&>::type type;
346
347            static type
348            call(Sequence& seq)
349            {
350                return seq.name;
351            };
352        };
353
354        template<typename Sequence>
355        struct apply<Sequence, fields::age>
356        {
357            typedef typename mpl::if_<
358                is_const<Sequence>,
359                int const&,
360                int&>::type type;
361
362            static type
363            call(Sequence& seq)
364            {
365                return seq.age;
366            };
367        };
368    };
369
370Its all very similar to the implementations we've seen previously,
371such as `deref_impl` and `value_of_impl`. Instead of identifying
372the members by index or position, we are now selecting them using
373the types `fields::name` and `fields::age`. The implementations of
374the other functions are equally straightforward, and are provided in
375the example code.
376
377[heading Summary]
378
379We've now worked through the entire process for adding a new random
380access sequence and we've also enabled our type to serve as an associative
381sequence. The implementation was slightly long-winded, but followed
382a simple repeating pattern.
383
384The support for `std::pair`, __mpl__ sequences, and `boost::array` all
385use the same approach, and provide additional examples of the approach
386for a variety of types.
387
388[endsect]
389
390[section Sequence Facade]
391
392[heading Description]
393The __sequence_facade__ template provides an intrusive mechanism for
394producing a conforming Fusion sequence.
395
396[heading Synopsis]
397    template<typename Derived, typename TravesalTag, typename IsView = mpl::false_>
398    struct sequence_facade;
399
400[heading Usage]
401The user of __sequence_facade__ derives his sequence type from a specialization of __sequence_facade__ and passes the derived sequence type as the first template parameter. The second template parameter should be the traversal category of the sequence being implemented. The 3rd parameter should be set to `mpl::true_` if the sequence is a view.
402
403The user must implement the key expressions required by their sequence type.
404
405[table Parameters
406[[Name][Description]]
407[[`sequence`, `Seq`][A type derived from __sequence_facade__]]
408[[`N`][An __mpl_integral_constant__]]
409]
410
411[table Key Expressions
412[[Expression][Result]]
413[[`sequence::template begin<Seq>::type`][The type of an iterator to the beginning of a sequence of type `Seq`]]
414[[`sequence::template begin<Seq>::call(seq)`][An iterator to the beginning of sequence `seq`]]
415[[`sequence::template end<Seq>::type`][The type of an iterator to the end of a sequence of type `Seq`]]
416[[`sequence::template end<Seq>::call(seq)`][An iterator to the end of sequence `seq`]]
417[[`sequence::template size<Seq>::type`][The size of a sequence of type `Seq` as an __mpl_integral_constant__]]
418[[`sequence::template size<Seq>::call(seq)`][The size of sequence `seq`]]
419[[`sequence::template empty<Seq>::type`][Returns `mpl::true_` if `Seq` has zero elements, `mpl::false_` otherwise.]]
420[[`sequence::template empty<Seq>::call`][Returns a type convertible to `bool` that evaluates to true if the sequence is empty, else, evaluates to false. ]]
421[[`sequence::template at<Seq, N>::type`][The type of element `N` in a sequence of type `Seq`]]
422[[`sequence::template at<Seq, N>::call(seq)`][Element `N` in sequence `seq`]]
423[[`sequence::template value_at<Sequence, N>::type`][The type of the `N`th element in a sequence of type `Seq`]]
424]
425
426[heading Include]
427
428    #include <boost/fusion/sequence/sequence_facade.hpp>
429    #include <boost/fusion/include/sequence_facade.hpp>
430
431[heading Example]
432A full working example using __sequence_facade__ is provided in triple.cpp in the extension examples.
433
434[endsect]
435
436[section Iterator Facade]
437
438[heading Description]
439The __iterator_facade__ template provides an intrusive mechanism for
440producing a conforming Fusion iterator.
441
442[heading Synopsis]
443
444    template<typename Derived, typename TravesalTag>
445    struct iterator_facade;
446
447[heading Usage]
448The user of iterator_facade derives his iterator type from a specialization of iterator_facade and passes the derived iterator type as the first template parameter. The second template parameter should be the traversal category of the iterator being implemented.
449
450The user must implement the key expressions required by their iterator type.
451
452[table Parameters
453[[Name][Description]]
454[[`iterator`, `It`, `It1`, `It2`][A type derived from __iterator_facade__]]
455[[`N`][An __mpl_integral_constant__]]
456]
457
458[table Key Expressions
459[[Expression][Result][Default]]
460[[`iterator::template value_of<It>::type`][The element stored at iterator position `It`][None]]
461[[`iterator::template deref<It>::type`][The type returned when dereferencing an iterator of type `It`][None]]
462[[`iterator::template deref<It>::call(it)`][Dereferences iterator `it`][None]]
463[[`iterator::template next<It>::type`][The type of the next element from `It`][None]]
464[[`iterator::template next<It>::call(it)`][The next iterator after `it`][None]]
465[[`iterator::template prior<It>::type`][The type of the next element from `It`][None]]
466[[`iterator::template prior<It>::call(it)`][The next iterator after `it`][None]]
467[[`iterator::template advance<It, N>::type`][The type of an iterator advanced `N` elements from `It`][Implemented in terms of `next` and `prior`]]
468[[`iterator::template advance<It, N>::call(it)`][An iterator advanced `N` elements from `it`][Implemented in terms of `next` and `prior`]]
469[[`iterator::template distance<It1, It2>::type`][The distance between iterators of type `It1` and `It2` as an __mpl_integral_constant__][None]]
470[[`iterator::template distance<It1, It2>::call(it1, it2)`][The distance between iterator `it1` and `it2`][None]]
471[[`iterator::template equal_to<It1, It2>::type`][Returns `mpl::true_` if `It1` is equal to `It2`, `mpl::false_` otherwise.][`boost::same_type<It1, It2>::type`]]
472[[`iterator::template equal_to<It1, It2>::call(it1, it2)`][Returns a type convertible to `bool` that evaluates to `true` if `It1` is equal to `It2`, `false` otherwise.][`boost::same_type<It1, It2>::type()`]]
473[[`iterator::template key_of<It>::type`][The key type associated with the element from `It`][None]]
474[[`iterator::template value_of_data<It>::type`][The type of the data property associated with the element from `It`][None]]
475[[`iterator::template deref_data<It>::type`][The type that will be returned by dereferencing the data property of the element from `It`][None]]
476[[`iterator::template deref_data<It>::call(it)`][Deferences the data property associated with the element referenced by `it`][None]]
477]
478
479[heading Header]
480
481    #include <boost/fusion/iterator/iterator_facade.hpp>
482    #include <boost/fusion/include/iterator_facade.hpp>
483
484[heading Example]
485A full working example using __iterator_facade__ is provided in triple.cpp in the extension examples.
486
487[endsect]
488
489[endsect]
490
491