1 // Copyright (C) 2019 T. Zachary Laine
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 //[ back_insert_iterator
7 #include <boost/stl_interfaces/iterator_interface.hpp>
8
9 #include <algorithm>
10 #include <vector>
11
12 #include <cassert>
13
14
15 // This is an output iterator that holds a reference to a container, and calls
16 // push_back() on that container when it is written to, just like
17 // std::back_insert_iterator. This is not a lot less code to write than the
18 // implementation of std::back_insert_iterator, but it demonstrates that
19 // iterator_interface is flexible enough to handle this odd kind of iterator.
20 template<typename Container>
21 struct back_insert_iterator : boost::stl_interfaces::iterator_interface<
22 back_insert_iterator<Container>,
23 std::output_iterator_tag,
24 typename Container::value_type,
25 back_insert_iterator<Container> &>
26 {
27 // For concept requirements.
back_insert_iteratorback_insert_iterator28 back_insert_iterator() : c_(nullptr) {}
29
30 // Construct from a container.
back_insert_iteratorback_insert_iterator31 explicit back_insert_iterator(Container & c) : c_(std::addressof(c)) {}
32
33 // When writing to *this, copy v into the container via push_back().
operator =back_insert_iterator34 back_insert_iterator & operator=(typename Container::value_type const & v)
35 {
36 c_->push_back(v);
37 return *this;
38 }
39 // When writing to *this, move v into the container via push_back().
operator =back_insert_iterator40 back_insert_iterator & operator=(typename Container::value_type && v)
41 {
42 c_->push_back(std::move(v));
43 return *this;
44 }
45
46 // Dereferencing *this just returns a reference to *this, so that the
47 // expression *it = value uses the operator=() overloads above.
operator *back_insert_iterator48 back_insert_iterator & operator*() { return *this; }
49 // There is no underlying sequence over which we are iterating, so there's
50 // nowhere to go in next(). Do nothing.
operator ++back_insert_iterator51 back_insert_iterator & operator++() { return *this; }
52
53 using base_type = boost::stl_interfaces::iterator_interface<
54 back_insert_iterator<Container>,
55 std::output_iterator_tag,
56 typename Container::value_type,
57 back_insert_iterator<Container> &>;
58 using base_type::operator++;
59
60 private:
61 Container * c_;
62 };
63
64 // A convenience function that creates a back_insert_iterator<Container>.
65 template<typename Container>
back_inserter(Container & c)66 back_insert_iterator<Container> back_inserter(Container & c)
67 {
68 return back_insert_iterator<Container>(c);
69 }
70
71
main()72 int main()
73 {
74 std::vector<int> ints = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}};
75 std::vector<int> ints_copy;
76 std::copy(ints.begin(), ints.end(), ::back_inserter(ints_copy));
77 assert(ints_copy == ints);
78 }
79 //]
80