Software_t
Software_t

Reputation: 586

What is the best way to change a set during iterations?

Given std::set , what is the best way to change the set during time-iteration?
For example:

std::set<T> s;  // T is a some type (it's not important for the question).
// insertions to s
for (std::set<T>::iterator it = s.begin(); it != s.end(); it++) {
        T saveIt(*it);
        s.erase(*it);
        s.insert( saveIt + saveIt );  // operator+ that defined at `T`
}

According to what that I read in some sources, it's bad way because that: the removing from the set may change the structure of the set.

So what is the better (/best) way to do it?

Upvotes: 1

Views: 98

Answers (2)

RvdK
RvdK

Reputation: 19790

Just have a copy std:set

std::set<T> s;
std::set<T> modified_s;
for (std::set<T>::iterator it = s.begin(); it != s.end(); it++) {
    modified_s.insert(*it+ *it);
}
s = std::move(modified_s);

Edit: Added std::move as improvement from @Jodocus

Upvotes: 0

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136228

Your loop may result in almost endless loop because you keep adding larger elements at the back of your set. Until T + T overflows.

Correct way is to create a new set:

std::set<T> s; 
std::set<T> s2; 
for(auto const& elem : s)
    s2.insert(elem + elem);
s.swap(s2);

With boost::range it is a one-liner:

#include <boost/range/adaptor/transformed.hpp>
// ...
std::set<int> s;
s = boost::copy_range<std::set<int>>(s | boost::adaptors::transformed([](int x) { return x + x; }));

Upvotes: 7

Related Questions