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