• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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