Каков наилучший способ изменить набор во время итераций? - PullRequest
0 голосов
/ 04 июля 2018

Учитывая std::set, каков наилучший способ изменить набор во время итерации?
Например:

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`
}

Согласно тому, что я читал в некоторых источниках, это плохой путь, потому что: удаление из набора может изменить структуру набора.

Так, каков лучший (/ лучший) способ сделать это?

Ответы [ 2 ]

0 голосов
/ 04 июля 2018

Просто скопируйте 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: Добавлено std::move как улучшение от @ Jodocus

0 голосов
/ 04 июля 2018

Ваш цикл может привести к почти бесконечному циклу, потому что вы продолжаете добавлять большие элементы в конце вашего набора. Пока T + T не переполнится.

Правильный способ - создать новый набор:

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

С boost::range это однострочный:

#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; }));
...