Special Standard Iterators Special Iterators Special Iterators
#include <iterator>
special input iterators = data sources
- extracting data:
value = *it
- advancing
position
:++it
special output iterators = data sinks
inserting
data:*it++ = value
Mostly used in conjunction with standard algorithms like
std::copy(@source_begin, @source_end, @target_begin) → @target_end
std::ranges::copy(source_range, @target_begin) → {@source_end, @target_end} C++20
Special input/output iterators cannot be used with algorithms that require forward, bidirectional or random access iterators.
- can be used to insert new elements into containers
- (only) useful if number of inserted elements not known in advance
- avoid in performance-critical code:
reserve container memory in advance and use a normal iterator instead
- output iterator: data sink / target
- single-pass: each
position
can only be accessed once - stores reference to container and insert position on construction
*it = value
calls.insert(position, value)
on a container- * and ++ are no-ops, * just returns a reference to the iterator itself
Best obtained with convenience function
std::inserter(container, position)
→ std::insert_iterator<ContainerType>{container, position}
#include <array>
#include <vector>
#include <iostream>
int main () {
std::vector<int> v {4, 8, 2};
std::array<int,2> a {5, 6};
copy(begin(a), end(a),
inserter(v, begin(v)+2));
for(int x : v) { std::cout << x <<' '; }
std::cout << '\n';
std::insert_iterator<
std::vector<int>> it {v,begin(v)+1};
*it = 1;
for(int x : v) { std::cout << x <<' '; }
std::cout << '\n';
}
- output iterator: data sink / target
- single-pass: each
position
can only be accessed once - stores reference to container on construction
*it = value
calls.push_back(value)
on a container- * and ++ are no-ops, * just returns a reference to the iterator itself
Best obtained with convenience function
std::back_inserter(container)
→ std::back_insert_iterator<ContainerType>{container}
#include <array>
#include <vector>
#include <iostream>
int main () {
std::vector<int> v {4, 8, 2};
std::array<int,2> a {5, 6};
copy(begin(a), end(a),
back_inserter(v));
for(int x : v) { std::cout << x <<' '; }
std::cout << '\n';
std::back_insert_iterator<
std::vector<int>> it {v};
*it = 1;
for(int x : v) { std::cout << x <<' '; }
std::cout << '\n';
}
v: - 4
- 8
- 2
a: - 5
- 6
v: - 4
- 8
- 2
- 5
- 6
v: - 4
- 8
- 2
- 5
- 6
- 1
- output iterator: data sink / target
- single-pass: each
position
can only be accessed once - stores reference to container on construction
*it = value
calls.push_front(value)
on a container- * and ++ are no-ops, * just returns a reference to the iterator itself
Best obtained with convenience function
std::front_inserter(container)
→ std::front_insert_iterator<ContainerType>{container}
#include <array>
#include <deque>
#include <iostream>
int main () {
std::deque<int> d {4, 8, 2};
std::array<int,2> a {5, 6};
copy(begin(a), end(a),
front_inserter(d));
for(int x : d) { std::cout << x <<' '; }
std::cout << '\n';
std::front_insert_iterator<
std::deque<int>> it {d};
*it = 1;
for(int x : d) { std::cout << x <<' '; }
std::cout << '\n';
}
d: - 4
- 8
- 2
a: - 5
- 6
d: - 6
- 5
- 4
- 8
- 2
d: - 1
- 6
- 5
- 4
- 8
- 2
- allow to use streams as sources or targets for standard algorithms
- should be avoided in performance-critical code
- output iterator: data sink / target
- single-pass: each
position
can only be accessed once - stores reference to output stream on construction
*it = value
puts value into stream- * and ++ are no-ops, * just returns a reference to the iterator itself
#include <vector>
#include <iterator>
#include <algorithm>
#include <iostream>
int main () {
std::vector<int> v {1,2,3,4};
copy(begin(v), end(v),
std::ostream_iterator<int>{std::cout});
std::cout << '\n';
copy(begin(v), end(v),
std::ostream_iterator<int>{std::cout," "});
std::cout << '\n';
copy(begin(v), end(v),
std::ostream_iterator<int>{std::cout,"/"});
std::cout << '\n';
}
1234
1 2 3 4
1/2/3/4
- input iterator: data source
- single-pass: each
position
can only be accessed once - stores reference to input stream on construction
*it
gets current value from stream++it
advances stream to next value- an
istream_iterator
constructed without argument can be used to indicate end-of-range
#include <fstream>
#include <vector>
#include <iterator>
#include <iostream>
int main () {
std::ifstream is {"numbers.txt"};
std::vector<int> v;
copy(std::istream_iterator<int>{is}, // src begin
std::istream_iterator<int>{}, // src end
back_inserter(v) ); // tgt begin
for(int x : v) { std::cout << x <<' '; }
std::cout << '\n';
}
#include <sstream>
#include <vector>
#include <iterator>
#include <iostream>
int main () {
std::istringstream str {"8 7 3 5 4"};
std::vector<int> w;
copy(std::istream_iterator<int>{str}, // src begin
std::istream_iterator<int>{}, // src end
back_inserter(w) ); // tgt begin
// w: - 8
- 7
- 3
- 5
- 4
for(int x : w) { std::cout << x <<' '; }
std::cout << '\n';
}
Standard Algorithm Compatibility Algorithm Compatibility Algorithms
The following tables list standard algorithms that are compatible with the special iterators presented above.
Since the special iterators are only input or output iterators they cannot be used with algorithms that require forward, bidirectional or random access iterators.
Changing Elements
transform
| In | Out |
replace_copy
| In | Out |
replace_copy_if
| In | Out |
fill_n
| — | Out |
generate_n
| — | Out |
Reordering
rotate_copy
| In | Out |
reverse_copy
| In | Out |
partial_sort_copy
| In | Out |
partition_copy
| In | Out |
is_partitioned
| In | — |
Removing
remove_copy
| In | Out |
remove_copy_if
| In | Out |
unique_copy
| In | Out |
Finding
find
| In | — |
find_if
| In | — |
find_if_not
| In | — |
find_first_of
| In | — |
Comparing
equal
| In | — |
mismatch
| In | — |
lexicographical_compare
| In | — |
lexicographical_compare_three_way
| In | — |
Traversal
for_each
| In | — |
for_each_n
| In | — |
Sorted Sequence Operations
includes
| In | — |
merge
| In | Out |
set_difference
| In | Out |
set_intersection
| In | Out |
set_union
| In | Out |
set_symmetric_difference
| In | Out |
Numeric Operations
accumulate
| In | — |
adjacent_difference
| In | Out |
exclusive_scan
| In | Out |
inclusive_scan
| In | Out |
inner_product
| In | — |
partial_sum
| In | Out |
reduce
| In | — |
transform_exclusive_scan
| In | Out |
transform_inclusive_scan
| In | Out |
transform_reduce
| In | — |