• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[/
2 / Distributed under the Boost Software License, Version 1.0. (See accompanying
3 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4 /]
5
6[section Introduction]
7
8Writing STL iterators, views, and containers is surprisingly hard.  There are a
9lot of things that can subtly go wrong.  It is also very tedious, which of
10course makes it error-prone.
11
12Iterators have numerous typedefs and operations, even though all the
13operations of a given iterator can be implemented in terms of at most four
14operations (and usually only three).  Writing all the other operations yields
15very similar-looking code that is hard to review, and all but requires that
16you write full-coverage tests for each iterator.
17
18Writing view types like those found in `std::ranges` is also laborious,
19considering that most of each view type's API can be derived from `begin()`
20and `end()`.  C++20 has a template that does exactly this,
21`std::ranges::view_interface`; _IFaces_ provides a pre-C++20-friendly
22implementation.
23
24Most daunting of all is the task of writing a type or template that meets the
25container requirements in the standard.  _IFaces_ provides another template
26called _cont_iface_ that reduces the implementation and testing burden
27dramatically.
28
29[note C++20 versions of _iter_iface_ and _cont_iface_ are provided (C++20
30provides `std::view_interface`).  These are constrained templates using C++20
31concepts.  These are in the `boost::stl_interfaces::v2` namespace, and are
32considered experimental, because at the time of this writing, no
33C++20-conforming compiler exists.]
34
35[heading A Quick Example]
36
37Here is an example of the iterator portion of the library.  Let's say that we
38wanted to make a random access iterator that represents a string of arbitrary
39length constructed by repeating a shorter string.  Let's call this iterator
40`repeated_chars_iterator`.  Here it is in action:
41
42[repeated_chars_iterator_usage]
43
44There's nothing in the standard library that gets us that kind of behavior, so
45we have to write it.  This library seeks to turn what we write from this:
46
47    struct repeated_chars_iterator
48    {
49        using value_type = char;
50        using difference_type = std::ptrdiff_t;
51        using pointer = char const *;
52        using reference = char const;
53        using iterator_category = std::random_access_iterator_tag;
54
55        constexpr repeated_chars_iterator() noexcept :
56            first_(nullptr),
57            size_(0),
58            n_(0)
59        {}
60        constexpr repeated_chars_iterator(
61            char const * first,
62            difference_type size,
63            difference_type n) noexcept :
64            first_(first),
65            size_(size),
66            n_(n)
67        {}
68
69        constexpr reference operator*() const noexcept
70        {
71            return first_[n_ % size_];
72        }
73
74        constexpr value_type operator[](difference_type n) const noexcept
75        {
76            return first_[(n_ + n) % size_];
77        }
78
79        constexpr repeated_chars_iterator & operator++() noexcept
80        {
81            ++n_;
82            return *this;
83        }
84        constexpr repeated_chars_iterator operator++(int)noexcept
85        {
86            repeated_chars_iterator retval = *this;
87            ++*this;
88            return retval;
89        }
90        constexpr repeated_chars_iterator & operator+=(difference_type n) noexcept
91        {
92            n_ += n;
93            return *this;
94        }
95
96        constexpr repeated_chars_iterator & operator--() noexcept
97        {
98            --n_;
99            return *this;
100        }
101        constexpr repeated_chars_iterator operator--(int)noexcept
102        {
103            repeated_chars_iterator retval = *this;
104            --*this;
105            return retval;
106        }
107        constexpr repeated_chars_iterator & operator-=(difference_type n) noexcept
108        {
109            n_ -= n;
110            return *this;
111        }
112
113        friend constexpr bool operator==(
114            repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept
115        {
116            return lhs.first_ == rhs.first_ && lhs.n_ == rhs.n_;
117        }
118        friend constexpr bool operator!=(
119            repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept
120        {
121            return !(lhs == rhs);
122        }
123        friend constexpr bool operator<(
124            repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept
125        {
126            return lhs.first_ == rhs.first_ && lhs.n_ < rhs.n_;
127        }
128        friend constexpr bool operator<=(
129            repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept
130        {
131            return lhs == rhs || lhs < rhs;
132        }
133        friend constexpr bool operator>(
134            repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept
135        {
136            return rhs < lhs;
137        }
138        friend constexpr bool operator>=(
139            repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept
140        {
141            return rhs <= lhs;
142        }
143
144        friend constexpr repeated_chars_iterator
145        operator+(repeated_chars_iterator lhs, difference_type rhs) noexcept
146        {
147            return lhs += rhs;
148        }
149        friend constexpr repeated_chars_iterator
150        operator+(difference_type lhs, repeated_chars_iterator rhs) noexcept
151        {
152            return rhs += lhs;
153        }
154        friend constexpr repeated_chars_iterator
155        operator-(repeated_chars_iterator lhs, difference_type rhs) noexcept
156        {
157            return lhs -= rhs;
158        }
159        friend constexpr difference_type operator-(
160            repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept
161        {
162            return lhs.n_ - rhs.n_;
163        }
164
165    private:
166        char const * first_;
167        difference_type size_;
168        difference_type n_;
169    };
170
171(that's a lot of code!) into this:
172
173[repeated_chars_iterator]
174
175Ah, that's better.  Both of these definitions for `repeated_chars_iterator`
176have the same semantics and performance profile.  It's just a lot less code to
177write the second one, and writing the second one is more novice-friendly.
178
179[note _IFaces_'s `iterator_interface` implements iterators that model the
180C++20 iterator concepts.]
181
182[endsect]
183
184[section This Library's Relationship to Boost.Iterator]
185
186_Iterator_ is a library that is already in Boost, and it has been around for a
187long time.
188
189However, it was attempting to solve a lot of problems related to iterators,
190not just how to write them from scratch.  It is also not easy to modernize it
191for use in C++11 and later.  Specifically:
192
193- _Iterator_ contains a large number of iterator adaptors; those have since
194  been rendered moot by C++20 ranges.
195
196- _Iterator_'s `iterator_facade` template is not limited just to the
197  existing standard C++ iterator categories; that was an experiment that never
198  landed in standard C++, so it adds needless complexity.
199
200- _Iterator_'s `iterator_facade` was written against C++98, so it is not
201  `constexpr`- and `noexcept`-friendly.
202
203- _Iterator_'s `iterator_facade` does not support proxy iterators, which
204  are fully supported by the C++20 iterator concepts.
205
206- There is opportunity to reduce the amount of code the user must write in
207  order to use `iterator_facade`.
208
209- _Iterator_ contains two templates, `iterator_facade` and `iterator_adaptor`,
210  that represent two ways of writing a new iterator while writing as little
211  code as possible.  It would be nice to have the functionality for both
212  available in one template, but it is difficult to unify those two templates
213  as written.
214
215For these reasons, it seems more appropriate to introduce a new Boost library
216than to try and address the shortcomings of _Iterator_'s `iterator_facade` and
217`iterator_adaptor` templates directly.
218
219[endsect]
220