How to neatly move some elements from std::set to another container? - c++

Since iterator invalidates upon remove operation, how do I iterate with the least amount of code over all the elements of std::set, removing some of them ?

// Filters the elements of a set: elements that satisfy the predicate 'pred'
// are removed from the source set and inserted into the output.
template <typename TSet, typename TOutputIterator, typename TPredicate>
void extract_if(TSet& s, TOutputIterator out, TPredicate pred)
{
for (typename TSet::iterator it(s.begin()); it != s.end();)
{
if (pred(*it))
{
*out++ = *it;
it = s.erase(it);
}
else
{
++it;
}
}
}

Related

c++ STL min_element

I want to find the minimum element in an array, but if the minimum element appears more than once, then I want the last occurrence of the element. I used std::min_element() with my comp() function.
vector<int>::iterator it=min_element(input.begin(), input.end(),comp);
cout << *it << endl;
cout << distance(input.begin(), it);
bool comp(int a, int b) {
if (a <= b)
return true;
else
return false;
}
This code is giving an error saying invalid comparator on input 3 3 4.
Give min_element reverse iterators instead:
vector<int>::reverse_iterator it=min_element(input.rbegin(), input.rend(),comp);
Then convert it back to a "normal" iterator iff you need to.
And don't forget to correct your comparator; it needs to be < not <=.
You might abuse of std::minmax_element which returns the last biggest element contrary to std::max_element:
auto last_min_it = std::minmax_element(input.begin(), input.end(), std::greater<>{}).second;
I would probably use reverse iterator with std::min_element, though:
auto min_rev_it = std::min_element(input.rbegin(), input.rend());
If your data are stored in a vector, then the use of a reverse iterator should suffice, as already suggested.
More generally, the Standard Library does not provide a min_element_last function, as also commented in 1. In this respect, a possible implementation of min_element_last may read:
template <typename I>
using ValueType = typename std::iterator_traits<I>::value_type;
template <typename I, typename R>
// I models ForwardIterator
// R models StrictWeakOrdering on ValueType<I>
I min_element_last(I first, I last, R cmp) {
if (first == last) return last;
I curr = first;
++first;
while (first != last) {
if (!cmp(*curr, *first)) {
curr = first;
}
++first;
}
return curr;
}
template <typename I>
// I models ForwardIterator
// ValueType<I> models TotallyOrdered
I min_element_last(I first, I last) {
using T = ValueType<I>;
return min_element_last(first, last, std::less<T>());
}
The advantage would be the possibility of using min_element_last also with iterators that only model the ForwardIterator concept.

How to implement end sentinel for back_insert_iterator?

I want to fill a container by consequtive values of iterators to elements of another container (often occured real life problem), say:
std::container1< T > c1{/* initialized */};
assert(!c1.empty());
std::continer2< typename std::container1< T >::iterator > c2;
auto it = std::begin(c1), const end = std::end(c1);
do { c2.push_back(it); } while (++it != end);
There is attractive std::iota algorithm in STL, but it is range-based and for std::back_inserter(c2) there is no way to achieve desired currently. However in the next versions of STL I can expect the iota algorithm of the form:
template< typename ForwardIterator, typename EndSentinel, typename T >
void
iota(ForwardIterator first, EndSentinel last, T value)
{
for (; first != last; ++first) {
*first = value;
++value;
}
}
How to implement EndSentinel and operator != (ForwardIterator, EndSentinel) to make above iota stop after exactly c1.size() step of the for loop in iota(std::back_inserter(c1), something(c1, c1.size()), std::begin(c1))?
There is no sentinel for std::back_insert_iterator (or any OutputIterator) and also no equality operator, because an output iterator is an "unlimited sequence": You can append elements to the end of a container or write to a file until you run out of memory or disk space.
However, it makes sense to have an output iterator with a sentinel if you need to call an algorithm which expects an "output sentinel" (because not expecting one may be unsafe if the output is a "limited sequence", such as a pre-allocated std::vector). Such an algorithm could look like:
template<typename InIter, typename InSentinel, typename OutIter, typename OutSentinel>
OutIter modernAlgorithm(InIter first, InSentinel last, OutIter outFirst, OutSentinel outLast);
In this case, all you need is a trivial sentinel, which compares unequal to everything. See also this answer.
template<typename T>
struct TrivialSentinel
{
bool operator==(const T&) { return false; }
bool operator!=(const T&) { return true; }
friend bool operator==(const T&, TrivialSentinel&) { return false; }
friend bool operator!=(const T&, TrivialSentinel&) { return true; }
};
modernAlgorithm(v.begin(), v.end(), std::back_inserter(r), TrivialSentinel<decltype(std::back_inserter(r))>());
(This may seem odd, but it does make sense if you consider that even if you repeat the same operation *out = expr on the same value of out, the output will be in a different state each time, so in a certain sense, no two output iterators are ever necessarily equivalent...)
However, older algorithms often don't allow the iterator and sentinel to have different types:
template<typename InIter, typename OutIter>
OutIter olderAlgorithm(InIter first, InIter last, OutIter outFirst, OutIter outLast);
In this case, you can write a sub class or wrapper of std::back_insert_iterator, which has a default constructor and always compares unequal to itself.
This is easy in C++20, where std::back_insert_iterator has a default constructor:
// C++20
template<typename C>
struct BackInsertIteratorWithSentinel : public std::back_insert_iterator<C>
{
BackInsertIteratorWithSentinel() {} // C++20 only
BackInsertIteratorWithSentinel(C& c) : std::back_insert_iterator<C>(c) {}
bool operator==(const BackInsertIteratorWithSentinel&) { return false; }
bool operator!=(const BackInsertIteratorWithSentinel&) { return true; }
};
template<typename C>
BackInsertIteratorWithSentinel<C> BackInserterWithSentinel(C& c)
{
return BackInsertIteratorWithSentinel<C>(c);
}
template<typename C>
BackInsertIteratorWithSentinel<C> BackInserterWithSentinel()
{
return BackInsertIteratorWithSentinel<C>();
}
olderAlgorithm(v.begin(), v.end(), BackInserterWithSentinel(r), BackInserterWithSentinel<std::vector<int> >());
Note that even in C++20, std::back_insert_iterator does not have an equality operator.
If you have to support older versions of C++, then you may have to implement your own std::back_insert_iterator from scratch, or use boost::optional or in-place construction to work around the lack of a default constructor.
Full test program for C++20
I dont think you can do it - or maybe I dont understand your question, but..
according to http://en.cppreference.com/w/cpp/algorithm/iota, this algorithm works on existing range of elements - so it does not make sense to use it with: std::back_inserter as first iterator which basicly is used to insert elements.
I want to fill a container by consequtive values of iterators to elements of another container
a different solution which uses generate_n:
live
std::vector<int> src = {0,1,2,3};
std::vector<std::vector<int>::iterator> dst;
std::generate_n(std::back_inserter(dst), src.size(), [it=src.begin()]() mutable {return it++;});
Your question includes an iota implementation which is different than the one in the standard I believe. Here is the standard version I know http://en.cppreference.com/w/cpp/algorithm/iota.
Your iota (which I will rename it as miota in my code) allows different type of iterators for begin and end.
What you want in the algorithm is; end sentinel needs to be different from begin (the inserter) until all values are processed. For processing values you only take one object and you use increment and copy-construction on that object.
Therefore, your end sentinel should know about the value processing and when finished the end sentinel should become equal to the inserter somehow.
I did it via holding begin/end iterators of the original container in a class called IotaHelper. This uses shared_ptr for sharing state with the sentinel class which is called IotaEndSentinel.
When you increment the value inside miota, it actually increments the begin iterator of the IotaHelper. When you check equality with the inserter and the sentinel it actually checks the iterator equality inside the IotaHelper.
All code with a basic example is here:
#include <iterator>
#include <numeric>
#include <vector>
#include <iostream>
#include <utility>
#include <memory>
template< typename ForwardIterator, typename EndSentinel, typename T >
void miota(ForwardIterator first, EndSentinel last, T value)
{
for (; first != last; ++first) {
*first = value;
++value;
}
}
template<typename Container>
struct IotaHelper
{
using Iterator = typename Container::iterator;
using IteratorPair = std::pair<Iterator, Iterator>;
IotaHelper(Iterator begin, Iterator end)
:
pair(std::make_shared<IteratorPair>(begin, end))
{ }
operator Iterator()
{
return pair->first;
}
IotaHelper& operator++()
{
++pair->first;
return *this;
}
std::shared_ptr<IteratorPair> pair;
};
template<typename Container>
struct IotaEndSentinel
{
using Helper = IotaHelper<Container>;
using Iterator = typename Helper::Iterator;
IotaEndSentinel(const Helper& helper)
:
helper(helper)
{}
template<typename C>
friend bool operator!=(const std::back_insert_iterator<C>& bii,
const IotaEndSentinel& sentinel)
{
return sentinel.helper.pair->first != sentinel.helper.pair->second;
}
Helper helper;
};
int main()
{
using Container0 = std::vector<int>;
using Container1 = std::vector<Container0::iterator>;
Container0 c0 = {1, 2, 3, 4, 5};
Container1 c1;
IotaHelper<Container0> iotaHelper(c0.begin(), c0.end());
miota(std::back_inserter(c1),
IotaEndSentinel<Container0>(iotaHelper),
iotaHelper);
std::cout << "Result: ";
for (auto iter : c1)
{
std::cout << *iter << ", ";
}
std::cout << std::endl;
}
I have tried to do this because it was fun. But please don't use this method for hacking output iterators like back_insert_iterator and make a generic method for yourself for different containers.
template<typename SourceContainer, typename IteratorContainer>
void FillIterators(SourceContainer& sc, IteratorContainer& ic)
{
for (auto iter = sc.begin(); iter != sc.end(); ++iter)
{
ic.insert(ic.end(), iter);
}
}
EDIT:
After using heap-allocation that code was smelling to me. Instead of trying to reason about the "value and the process" we can reason about the "iterators and the process".
We can build an iterator-wrapper which contains the process iterator and the insert iterator together.
When the algorithm needs to dereference the wrapper, it will return the insert iterator.
When the algorithm needs to compare to other "wrapper or sentinel", wrapper will compare the process iterator.
In the end we can use such iterator for both std::iota and your miota.
Complete example is here:
#include <iterator>
#include <numeric>
#include <vector>
#include <iostream>
#include <utility>
#include <memory>
template< typename ForwardIterator, typename EndSentinel, typename T >
void miota(ForwardIterator first, EndSentinel last, T value)
{
for (; first != last; ++first) {
*first = value;
++value;
}
}
template<typename InsertIterator, typename Iterator>
struct InsertWrapper
{
InsertWrapper(const InsertIterator& inserter, const Iterator& iter)
:
inserter(inserter),
iter(iter)
{ }
bool operator!=(const InsertWrapper& other) const
{
//only compare process iterators
return iter != other.iter;
}
bool operator!=(const Iterator& sentinel) const
{
//compare process iterator against the sentinel
return iter != sentinel;
}
InsertIterator& operator*()
{
//return inserter for dereference
return inserter;
}
InsertWrapper& operator++()
{
//iterate inserter as the process progresses
++inserter;
++iter;
return *this;
}
InsertIterator inserter;
Iterator iter;
};
template<typename InsertIterator, typename Iterator>
InsertWrapper<InsertIterator, Iterator> WrapInserter(const InsertIterator& inserter,
const Iterator& iter)
{
return InsertWrapper<InsertIterator, Iterator>(inserter, iter);
}
int main()
{
using Container0 = std::vector<int>;
using Container1 = std::vector<Container0::iterator>;
Container0 c0 = {1, 2, 3, 4, 5};
Container1 c1;
//use wrapper as usual iterator begin/end
std::iota(WrapInserter(std::back_inserter(c1), c0.begin()),
WrapInserter(std::back_inserter(c1), c0.end()),
c0.begin());
std::cout << "std::iota result: ";
for (auto iter : c1)
{
std::cout << *iter << ", ";
}
std::cout << std::endl;
c1.clear();
miota(WrapInserter(std::back_inserter(c1), c0.begin()),
c0.end(), //end iterator as sentinel
c0.begin());
std::cout << "miota result: ";
for (auto iter : c1)
{
std::cout << *iter << ", ";
}
std::cout << std::endl;
}

EXC Bad Access with Iterators

I created this function that works with vectors, linked lists and double linked lists. The function takes a value and searches for it in the container. If the vlaue is in the container than the function will insert the value right next to where it already exists. So, if val=2 then {3,2,5} will become {3,2,2,5}. But if the value does not exist in the container, it is added to the back instead.
I wrote this function using iterators. It works just fine with a vector, however when I try to run it with a list or double linked list I get an Exc Bad Access error at the line if (*it==val). I am not seeing what I did wrong.
template <class Container, class T>
void insertNextTo( Container &x, const T &val){
typename Container::iterator it = x.begin();
while (it!=x.end() && *it!=val){
++it;
}
if (*it == val){
x.insert(it, val);
}
else{
x.push_back(val);
}
}
Edit: Thank you everyone! Your suggestion to change the if statement worked perfectly!
Change
if (*it == val)
to:
if (it != x.end())
If val isn't found in the container, the loop will end when it == x.end(). That points past the end of the array, so indirecting through it results in undefined behavior.
If the value does not exist yet, it will be equal to end() when the loop is finished, and you cannot dereference end(). You need to change if (*it == val) to if (it != x.end()) instead:
//if (*it == val){
if (it != x.end()){
x.insert(it, val);
}
Alternatively, since you are only inserting one value, if you find val then you can do the insert() and exit the function immediately, and then push_back() only if the loop reaches the end of the container:
template <class Container, class T>
void insertNextTo( Container &x, const T &val ) {
typename Container::iterator it = x.begin();
while (it != x.end()) {
if (*it == val) {
x.insert(it, val);
return;
}
++it;
}
x.push_back(val);
}
In which case, you can simplify the code by using std::find() instead of a manual loop:
#include <algorithm>
template <class Container, class T>
void insertNextTo( Container &x, const T &val ) {
typename Container::iterator it = std::find(x.begin(), x.end(), val);
if (it != x.end()) {
x.insert(it, val);
} else {
x.push_back(val);
}
}
Or even this, since it is safe to insert() using the end() iterator, it is effectively the same as push_back():
template <class Container, class T>
void insertNextTo( Container &x, const T &val ) {
typename Container::iterator it = std::find(x.begin(), x.end(), val);
x.insert(it, val);
}
Someone correct me if I'm wrong but I believe your error comes from the fact that the when your iterator reaches the end of the list, it actually points to the address after the last bit of the list in memory, which may or may not be initialized and in scope, which causes your program to error.

Move all elements which satisfy some condition from one container to another, i.e. I'm looking for some kind of "move_if"

Given
std::vector<T> first = /* some given data */, second;
I want to move all elements e which satisfy some condition cond(e) from first to second, i.e. something like
move_if(std::make_move_iterator(first.begin()),
std::make_move_iterator(first.end()),
std::back_inserter(second), [&](T const& e)
{
return cond(e);
});
I wasn't able to establish this with the algorithms library. So, how can I do that?
If the moved-from elements can stay where they are in first, then just use copy_if with move_iterator.
std::copy_if(std::make_move_iterator(first.begin()),
std::make_move_iterator(first.end()),
std::back_inserter(second), cond);
If the moved-from elements should be erased from first, I'd do
// partition: all elements that should not be moved come before
// (note that the lambda negates cond) all elements that should be moved.
// stable_partition maintains relative order in each group
auto p = std::stable_partition(first.begin(), first.end(),
[&](const auto& x) { return !cond(x); });
// range insert with move
second.insert(second.end(), std::make_move_iterator(p),
std::make_move_iterator(first.end()));
// erase the moved-from elements.
first.erase(p, first.end());
Or partition_copy with a move_iterator, followed by assignment:
std::vector<T> new_first;
std::partition_copy(std::make_move_iterator(first.begin()),
std::make_move_iterator(first.end()),
std::back_inserter(second), std::back_inserter(new_first), cond);
first = std::move(new_first);
The reason why move_if doesn't exist is because it would bloat the library. Either use copy_if with move iterator or write it yourself.
copy_if(move_iterator<I>(f), move_iterator<I>(l), out);
Here is an implementation by Jonas_No found at channel9.
template <typename FwdIt, typename Container, typename Predicate>
inline FwdIt move_if(FwdIt first, FwdIt last, Container &cont, Predicate pred)
{
if (first == last)
return last; // Empty so nothing to move
const size_t size = count_if(first, last, pred);
if (size == 0)
return last; // Nothing to move
cont.resize(size);
FwdIt new_end = first;
auto c = cont.begin();
for (auto i = first; i != last; ++i)
{
if (pred(*i)) // Should it move it ?
*c++ = move(*i);
else
*new_end++ = move(*i);
}
return new_end;
}
#T.C. has provided a perfectly working solution. However, at a first glance, one may not understand what the intend of that code is. So, it might be not perfect, but I tend to prefer something like this:
template<class InputIt, class OutputIt, class InputContainer, class UnaryPredicate>
OutputIt move_and_erase_if(InputIt first, InputIt last, InputContainer& c, OutputIt d_first, UnaryPredicate pred)
{
auto dist = std::distance(first, last);
while (first != last)
{
if (pred(*first))
{
*d_first++ = std::move(*first);
first = c.erase(first);
last = std::next(first, --dist);
}
else
{
++first;
--dist;
}
}
return d_first;
}

Finding elements in std::set

Given that I have a std::set, how do I find out if one element of the set is before the other. For example, something like this -
bool before(const std::set &s, const int first, const int second) const {
auto it_first = s.find(first);
auto it_second = s.find(second);
return it_first <= it_second;
}
The above code does not work since <= is not defined for the bidirectional iterators, but how would one go about doing something like this?
A set orders its elements by operator< (by default). The comparator itself can be retrieved via key_comp or value_comp. So if both elements are in the set, the order is defined by the elements themselves - you don't need the iterators:
return s.key_comp()(first, second);
If one or neither are in the set, then it depends on what you want to do in those cases:
if (s.count(first)) {
if (s.count(second)) {
return s.key_comp()(first, second);
}
else {
/* no second */
}
}
else {
/* no first, possibly second */
}
If you would look more generic solution than only for std::set this method would work for any container with forward iterator:
template <class T>
bool before( const T &cont, typename T::const_iterator first, typename T::const_iterator second )
{
for( auto it = cont.begin(); true; ++it ) {
if( it == first ) return true;
if( it == second ) return false;
}
}
assuming first and second are valid iterators. Now you can have more optimal specialization for std::set and std::map:
return cont.key_comp()( *first, *second );
and for container with random access iterator:
return first < second;