Reputation: 887
I'd like to fill a std::map
using std::generate_n
but can't get it to work. What I tried is something along these lines:
unsigned number_of_pairs{5};
std::map<std::string, std::string> my_map;
auto read_pair_from_input = [](){
std::string key;
std::getline(std::cin, key);
std::string value;
std::getline(std::cin, value);
return std::make_pair(key, value);
};
std::generate_n(my_map.begin(), number_of_pairs, read_pair_from_input);
This gives me long errors like:
In file included from /opt/wandbox/gcc- head/include/c++/8.0.0/algorithm:62:0,
from prog.cc:1:
/opt/wandbox/gcc-head/include/c++/8.0.0/bits/stl_algo.h: In instantiation of '_OIter std::generate_n(_OIter, _Size, _Generator) [with _OIter = std::_Rb_tree_iterator<std::pair<const std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> > >; _Size = unsigned int; _Generator = main()::<lambda()>]':
prog.cc:18:74: required from here
/opt/wandbox/gcc-head/include/c++/8.0.0/bits/stl_algo.h:4468:11: error: use of deleted function 'std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator= (typename std::conditional<std::__not_<std::__and_<std::is_copy_assignable<_Tp>, std::is_copy_assignable<_T2> > >::value, const std::pair<_T1, _T2>&, const std::__nonesuch_no_braces&>::type) [with _T1 = const std::__cxx11::basic_string<char>; _T2 = std::__cxx11::basic_string<char>; typename std::conditional<std::__not_<std::__and_<std::is_copy_assignable<_Tp>, std::is_copy_assignable<_T2> > >::value, const std::pair<_T1, _T2>&, const std::__nonesuch_no_braces&>::type = const std::pair<const std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >&]'
*__first = __gen();
~~~~~~~~~^~~~~~~~~
In file included from /opt/wandbox/gcc-head/include/c++/8.0.0/utility:70:0,
from /opt/wandbox/gcc-head/include/c++/8.0.0/algorithm:60,
from prog.cc:1:
/opt/wandbox/gcc-head/include/c++/8.0.0/bits/stl_pair.h:378:7: note: declared here
operator=(typename conditional<
^~~~~~~~
Is it possible to fill a std::map
with std::generate_n
?
Upvotes: 12
Views: 2672
Reputation: 181068
std::generate_n can be implemented like
template< class OutputIt, class Size, class Generator >
OutputIt generate_n( OutputIt first, Size count, Generator g )
{
for( Size i = 0; i < count; i++ ) {
*first++ = g();
}
return first;
}
As you can see it tries to assign the result of the generator to the iterator. This does not work with associative containers as you cannot modify the key as that would break the structure of the container.
What you need is different type of iterator, namely a std::insert_iterator
that you can get using std::inserter
like
std::generate_n(std::inserter(my_map, my_map.begin()), number_of_pairs, read_pair_from_input);
Upvotes: 23
Reputation: 41220
What you want is a std::inserter
:
std::generate_n(std::inserter(my_map, my_map.begin()), number_of_pairs, read_pair_from_input);
The inserter
will wrap your map
into an iterator-like construct that std::generate_n
can use
Upvotes: 26