Velvet Star Monitor

Standout celebrity highlights with iconic style.

news

Fill std::map with std::generate_n

Writer Sebastian Wright

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?

0

2 Answers

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

Demo

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);

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy