1 ///////////////////////////////////////////////////////////////////////////////
2 /// \file iterator.hpp
3 /// Proto callables for std functions found in \<iterator\>
4 //
5 //  Copyright 2012 Eric Niebler. Distributed under the Boost
6 //  Software License, Version 1.0. (See accompanying file
7 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 
9 #ifndef BOOST_PROTO_FUNCTIONAL_STD_ITERATOR_HPP_EAN_27_08_2012
10 #define BOOST_PROTO_FUNCTIONAL_STD_ITERATOR_HPP_EAN_27_08_2012
11 
12 #include <iterator>
13 #include <boost/type_traits/remove_const.hpp>
14 #include <boost/type_traits/remove_reference.hpp>
15 #include <boost/proto/proto_fwd.hpp>
16 
17 namespace boost { namespace proto { namespace functional
18 {
19 
20     // A PolymorphicFunctionObject wrapping std::advance
21     struct advance
22     {
23         BOOST_PROTO_CALLABLE()
24 
25         typedef void result_type;
26 
27         template<typename InputIterator, typename Distance>
operator ()boost::proto::functional::advance28         void operator()(InputIterator &x, Distance n) const
29         {
30             std::advance(x, n);
31         }
32     };
33 
34     // A PolymorphicFunctionObject wrapping std::distance
35     struct distance
36     {
37         BOOST_PROTO_CALLABLE()
38 
39         template<typename Sig>
40         struct result;
41 
42         template<typename This, typename InputIter1, typename InputIter2>
43         struct result<This(InputIter1, InputIter2)>
44         {
45             typedef
46                 typename std::iterator_traits<
47                     typename boost::remove_const<
48                         typename boost::remove_reference<InputIter1>::type
49                     >::type
50                 >::difference_type
51             type;
52         };
53 
54         template<typename InputIterator>
55         typename std::iterator_traits<InputIterator>::difference_type
operator ()boost::proto::functional::distance56         operator()(InputIterator first, InputIterator last) const
57         {
58             return std::distance(first, last);
59         }
60     };
61 
62     // A PolymorphicFunctionObject wrapping std::next
63     struct next
64     {
65         BOOST_PROTO_CALLABLE()
66 
67         template<typename Sig>
68         struct result;
69 
70         template<typename This, typename ForwardIterator>
71         struct result<This(ForwardIterator)>
72         {
73             typedef
74                 typename boost::remove_const<
75                     typename boost::remove_reference<ForwardIterator>::type
76                 >::type
77             type;
78         };
79 
80         template<typename This, typename ForwardIterator, typename Distance>
81         struct result<This(ForwardIterator, Distance)>
82         {
83             typedef
84                 typename boost::remove_const<
85                     typename boost::remove_reference<ForwardIterator>::type
86                 >::type
87             type;
88         };
89 
90         template<typename ForwardIterator>
operator ()boost::proto::functional::next91         ForwardIterator operator()(ForwardIterator x) const
92         {
93             return std::advance(
94                 x
95               , static_cast<typename std::iterator_traits<ForwardIterator>::difference_type>(1)
96             );
97         }
98 
99         template<typename ForwardIterator>
operator ()boost::proto::functional::next100         ForwardIterator operator()(
101             ForwardIterator x
102           , typename std::iterator_traits<ForwardIterator>::difference_type n
103         ) const
104         {
105             return std::advance(x, n);
106         }
107     };
108 
109     // A PolymorphicFunctionObject wrapping std::prior
110     struct prior
111     {
112         BOOST_PROTO_CALLABLE()
113 
114         template<typename Sig>
115         struct result;
116 
117         template<typename This, typename BidirectionalIterator>
118         struct result<This(BidirectionalIterator)>
119         {
120             typedef
121                 typename boost::remove_const<
122                     typename boost::remove_reference<BidirectionalIterator>::type
123                 >::type
124             type;
125         };
126 
127         template<typename This, typename BidirectionalIterator, typename Distance>
128         struct result<This(BidirectionalIterator, Distance)>
129         {
130             typedef
131                 typename boost::remove_const<
132                     typename boost::remove_reference<BidirectionalIterator>::type
133                 >::type
134             type;
135         };
136 
137         template<typename BidirectionalIterator>
operator ()boost::proto::functional::prior138         BidirectionalIterator operator()(BidirectionalIterator x) const
139         {
140             return std::advance(
141                 x
142               , -static_cast<typename std::iterator_traits<BidirectionalIterator>::difference_type>(1)
143             );
144         }
145 
146         template<typename BidirectionalIterator>
operator ()boost::proto::functional::prior147         BidirectionalIterator operator()(
148             BidirectionalIterator x
149           , typename std::iterator_traits<BidirectionalIterator>::difference_type n
150         ) const
151         {
152             return std::advance(x, -n);
153         }
154     };
155 
156 }}}
157 
158 #endif
159