Creating a generic insertion iterator, part 1
We provide the boilerplate; you provide the smarts. The post Creating a generic insertion iterator, part 1 appeared first on The Old New Thing.
![Creating a generic insertion iterator, part 1](https://devblogs.microsoft.com/oldnewthing/wp-content/uploads/sites/38/2019/02/ShowCover.jpg)
Last time, we created an inserter iterator that does unhinted insertion. We noticed that most of the iterator is just boilerplate, so let’s generalize it into a version that is all-boilerplate.
// Do not use: See discussion templatestruct generic_output_iterator { using iterator_category = std::output_iterator_tag; using value_type = void; using pointer = void; using reference = void; using difference_type = void; generic_output_iterator(Lambda&& lambda) : insert(std::forward (lambda)) {} generic_output_iterator& operator*() noexcept { return *this; } generic_output_iterator& operator++() noexcept { return *this; } generic_output_iterator& operator++(int) noexcept { return *this; } template generic_output_iterator& operator=( Value&& value) { insert(std::forward (value)); return *this; } protected: std::decay_t insert; }; template generic_output_iterator generic_output_inserter(Lambda&& lambda) { return generic_output_iterator ( std::forward (lambda)); } template generic_output_iterator(Lambda&&) -> generic_output_iterator ;
For convenience, I provided both a deduction guide and a maker function, so you can use whichever version appeals to you.¹
The generic output iterator uses the lambda to process each insertion. You can make the lambda do anything you like. For example:
auto sample(std::vector& v) { std::map m; std::copy(v.begin(), v.end(), generic_output_iterator( [&m, hint = m.begin()](int v) mutable { hint = m.insert(hint, { v, 0 }); })); }
In this example, we take a vector of what we expect to be a mostly-sorted sequence of integers and use them as keys in a newly-created map, where the associated integer is initialized to zero. We take advantage of the mostly-sorted-ness by using the location of the previously-inserted item as the hint for the next item.
Too bad this is not a valid iterator!
Among the requirements for iterators is that they be default-constructible and assignable, and ours is neither because capturing lambdas are neither default-constructible nor assignable. (Capturing lambdas can be copy-constructible and move-constructible, but they are never default-constructible or assignable.)
We’ll try to fix this problem next time.
¹ The C++ standard library has a lot of maker functions because they predate class template argument deduction (CTAD) and deduction guides.
The post Creating a generic insertion iterator, part 1 appeared first on The Old New Thing.