I need to flatten a container from std::map<int, std::set<std::string>>
to std::set<std::string>
and I am running to difficulties with the syntax. When I say flatten, I basically want to make a single std::set<string>
with all the sets stitched together - (the set
will prevent duplicates entries which is what I need) I was trying something based on the answer in this question but my value type is a container which makes the problem harder to solve. The output from the compiler is very difficult to understand, here the source is shown below.
I have a live coliru of my code here
int main()
{
std::set<std::string> outputSet;
std::map<int, std::set<std::string>> inputMap = {
{1, {"a", "b", "c"}},
{2, {"b", "c", "d"}}
};
std::transform(inputMap.cbegin(), inputMap.cend(),
std::inserter(outputSet, outputSet.end()),
[](const std::map<int, std::set<std::string>>::value_type& rNext) {
return rNext.second;
});
}
The errors are shown below:
In file included from /usr/local/include/c++/6.2.0/algorithm:62:0,
from main.cpp:4:
/usr/local/include/c++/6.2.0/bits/stl_algo.h: In instantiation of '_OIter std::transform(_IIter, _IIter, _OIter, _UnaryOperation) [with _IIter = std::_Rb_tree_const_iterator<std::pair<const int, std::set<std::__cxx11::basic_string<char> > > >; _OIter = std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >; _UnaryOperation = main()::<lambda(const value_type&)>]':
main.cpp:19:10: required from here
/usr/local/include/c++/6.2.0/bits/stl_algo.h:4177:12: error: no match for 'operator=' (operand types are 'std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >' and 'std::set<std::__cxx11::basic_string<char> >')
*__result = __unary_op(*__first);
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/local/include/c++/6.2.0/bits/stl_algobase.h:67:0,
from /usr/local/include/c++/6.2.0/bits/stl_tree.h:63,
from /usr/local/include/c++/6.2.0/set:60,
from main.cpp:1:
/usr/local/include/c++/6.2.0/bits/stl_iterator.h:680:7: note: candidate: std::insert_iterator<_Container>& std::insert_iterator<_Container>::operator=(const typename _Container::value_type&) [with _Container = std::set<std::__cxx11::basic_string<char> >; typename _Container::value_type = std::__cxx11::basic_string<char>]
operator=(const typename _Container::value_type& __value)
^~~~~~~~
/usr/local/include/c++/6.2.0/bits/stl_iterator.h:680:7: note: no known conversion for argument 1 from 'std::set<std::__cxx11::basic_string<char> >' to 'const value_type& {aka const std::__cxx11::basic_string<char>&}'
/usr/local/include/c++/6.2.0/bits/stl_iterator.h:688:7: note: candidate: std::insert_iterator<_Container>& std::insert_iterator<_Container>::operator=(typename _Container::value_type&&) [with _Container = std::set<std::__cxx11::basic_string<char> >; typename _Container::value_type = std::__cxx11::basic_string<char>]
operator=(typename _Container::value_type&& __value)
^~~~~~~~
/usr/local/include/c++/6.2.0/bits/stl_iterator.h:688:7: note: no known conversion for argument 1 from 'std::set<std::__cxx11::basic_string<char> >' to 'std::set<std::__cxx11::basic_string<char> >::value_type&& {aka std::__cxx11::basic_string<char>&&}'
/usr/local/include/c++/6.2.0/bits/stl_iterator.h:629:11: note: candidate: constexpr std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >& std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >::operator=(const std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >&)
class insert_iterator
^~~~~~~~~~~~~~~
/usr/local/include/c++/6.2.0/bits/stl_iterator.h:629:11: note: no known conversion for argument 1 from 'std::set<std::__cxx11::basic_string<char> >' to 'const std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >&'
/usr/local/include/c++/6.2.0/bits/stl_iterator.h:629:11: note: candidate: constexpr std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >& std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >::operator=(std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >&&)
/usr/local/include/c++/6.2.0/bits/stl_iterator.h:629:11: note: no known conversion for argument 1 from 'std::set<std::__cxx11::basic_string<char> >' to 'std::insert_iterator<std::set<std::__cxx11::basic_string<char> > >&&'
The std::insert_iterator
you're creating using std::inserter
expects to be assigned a single element which it will then insert into the container, but you're attempting to assign an entire set
to it.
std::for_each
is better suited to what you're trying to do
std::for_each(inputMap.cbegin(), inputMap.cend(),
[&](auto const& m) {
outputSet.insert(m.second.begin(), m.second.end());
});