std::back_inserter for a std::set?

C++AlgorithmStl

C++ Problem Overview


I guess this is a simple question. I need to do something like this:

std::set<int> s1, s2;
s1 = getAnExcitingSet();
std::transform(s1.begin(), s1.end(), std::back_inserter(s2), ExcitingUnaryFunctor());

Of course, std::back_inserter doesn't work since there's no push_back. std::inserter also needs an iterator? I haven't used std::inserter so I'm not sure what to do.

Does anyone have an idea?


Of course, my other option is to use a vector for s2, and then just sort it later. Maybe that's better?

C++ Solutions


Solution 1 - C++

set doesn't have push_back because the position of an element is determined by the comparator of the set. Use std::inserter and pass it .begin():

std::set<int> s1, s2;
s1 = getAnExcitingSet();
transform(s1.begin(), s1.end(), 
          std::inserter(s2, s2.begin()), ExcitingUnaryFunctor());

The insert iterator will then call s2.insert(s2.begin(), x) where x is the value passed to the iterator when written to it. The set uses the iterator as a hint where to insert. You could as-well use s2.end().

Solution 2 - C++

In 2016 there was a proposal to have a "single argument inserter iterator". https://isocpp.org/files/papers/p0471r0.html . I couldn't find if it the proposal advanced. I think it makes sense.

For now you can have this behavior defining the maker function:

template<class Container>
auto sinserter(Container& c){
	using std::end;
	return std::inserter(c, end(c));
}

Used as:

std::transform(begin(my_vec), end(my_vec), sinserter(my_set), [](auto& e){return e.member;});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrlbondView Question on Stackoverflow
Solution 1 - C++Johannes Schaub - litbView Answer on Stackoverflow
Solution 2 - C++alfCView Answer on Stackoverflow