Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fill std::map with std::generate_n

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?

like image 778
DenverCoder21 Avatar asked Jul 18 '17 12:07

DenverCoder21


2 Answers

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);
like image 86
NathanOliver Avatar answered Nov 20 '22 05:11

NathanOliver


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

like image 25
AndyG Avatar answered Nov 20 '22 04:11

AndyG