1 /*=============================================================================
2     Copyright (c) 2005-2013 Joel de Guzman
3     Copyright (c) 2005-2006 Dan Marsden
4 
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #if !defined(BOOST_FUSION_MAP_ITERATOR_02042013_0835)
9 #define BOOST_FUSION_MAP_ITERATOR_02042013_0835
10 
11 #include <boost/fusion/support/config.hpp>
12 #include <boost/fusion/iterator/iterator_facade.hpp>
13 #include <boost/mpl/minus.hpp>
14 #include <boost/mpl/equal_to.hpp>
15 #include <boost/mpl/if.hpp>
16 #include <boost/utility/declval.hpp>
17 #include <boost/type_traits/is_const.hpp>
18 #include <boost/type_traits/add_const.hpp>
19 
20 namespace boost { namespace fusion
21 {
22     struct random_access_traversal_tag;
23 
24     template <typename Seq, int Pos>
25     struct map_iterator
26         : iterator_facade<
27             map_iterator<Seq, Pos>
28           , typename Seq::category>
29     {
30         typedef Seq sequence;
31         typedef mpl::int_<Pos> index;
32 
33         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
map_iteratorboost::fusion::map_iterator34         map_iterator(Seq& seq)
35             : seq_(seq)
36         {}
37 
38         template<typename Iterator>
39         struct value_of
40         {
41             typedef typename Iterator::sequence sequence;
42             typedef typename Iterator::index index;
43             typedef
44                 decltype(boost::declval<sequence>().get_val(index()))
45             type;
46         };
47 
48         template<typename Iterator>
49         struct value_of_data
50         {
51             typedef typename Iterator::sequence sequence;
52             typedef typename Iterator::index index;
53             typedef
54                 decltype(boost::declval<sequence>().get_val(index()).second)
55             type;
56         };
57 
58         template<typename Iterator>
59         struct key_of
60         {
61             typedef typename Iterator::sequence sequence;
62             typedef typename Iterator::index index;
63             typedef decltype(boost::declval<sequence>().get_key(index())) key_identity_type;
64             typedef typename key_identity_type::type type;
65         };
66 
67         template<typename Iterator>
68         struct deref
69         {
70             typedef typename Iterator::sequence sequence;
71             typedef typename Iterator::index index;
72             typedef
73                 decltype(boost::declval<sequence>().get(index()))
74             type;
75 
76             BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
77             static type
callboost::fusion::map_iterator::deref78             call(Iterator const& it)
79             {
80                 return it.seq_.get(typename Iterator::index());
81             }
82         };
83 
84         template<typename Iterator>
85         struct deref_data
86         {
87             typedef typename Iterator::sequence sequence;
88             typedef typename Iterator::index index;
89 
90             typedef decltype(boost::declval<sequence>().get(index()).second) second_type_;
91 
92             typedef typename
93                 mpl::if_<
94                     is_const<sequence>
95                   , typename add_const<second_type_>::type
96                   , second_type_
97                 >::type
98             second_type;
99 
100             typedef typename add_reference<second_type>::type type;
101 
102             BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
103             static type
callboost::fusion::map_iterator::deref_data104             call(Iterator const& it)
105             {
106                 return it.seq_.get(typename Iterator::index()).second;
107             }
108         };
109 
110         template <typename Iterator, typename N>
111         struct advance
112         {
113             typedef typename Iterator::index index;
114             typedef typename Iterator::sequence sequence;
115             typedef map_iterator<sequence, index::value + N::value> type;
116 
117             BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
118             static type
callboost::fusion::map_iterator::advance119             call(Iterator const& i)
120             {
121                 return type(i.seq_);
122             }
123         };
124 
125         template<typename Iterator>
126         struct next
127             : advance<Iterator, mpl::int_<1> >
128         {};
129 
130         template<typename Iterator>
131         struct prior
132             : advance<Iterator, mpl::int_<-1> >
133         {};
134 
135         template <typename I1, typename I2>
136         struct distance
137         {
138             typedef typename
139                 mpl::minus<
140                     typename I2::index, typename I1::index
141                 >::type
142             type;
143 
144             BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
145             static type
callboost::fusion::map_iterator::distance146             call(I1 const&, I2 const&)
147             {
148                 return type();
149             }
150         };
151 
152         template<typename I1, typename I2>
153         struct equal_to
154             : mpl::equal_to<typename I1::index, typename I2::index>
155         {};
156 
157         Seq& seq_;
158 
159     private:
160         // silence MSVC warning C4512: assignment operator could not be generated
161         map_iterator& operator= (map_iterator const&);
162     };
163 
164 }}
165 
166 #ifdef BOOST_FUSION_WORKAROUND_FOR_LWG_2408
167 namespace std
168 {
169     template <typename Seq, int Pos>
170     struct iterator_traits< ::boost::fusion::map_iterator<Seq, Pos> >
171     { };
172 }
173 #endif
174 
175 #endif
176