Trouble with std::map::emplace syntax - c++

I am trying to emplace data into a std::map. Below is what I have tried (trimmed from the original source but definitely gives the idea):
template<typename T> class trie {
private:
std::map<typename T::value_type, std::unique_ptr<trie<T>>> children;
std::unique_ptr<trie<T>> parent;
// Later
public:
trie(const trie<T>& other, trie<T>* const parent) :
parent{parent}
{
for(auto const &it : other.children)
children.emplace(it.first, {*it.second});
}
};
The error is as follows:
trie.h: In instantiation of ‘trie<T>::trie(const trie<T>&, trie<T>*) [with T = std::basic_string<char>]’:
main.cpp:7:23: required from here
trie.h:90:3: error: no matching function for call to ‘std::map<char, std::unique_ptr<trie<std::basic_string<char> >, std::default_delete<trie<std::basic_string<char> > > >, std::less<char>, std::allocator<std::pair<const char, std::unique_ptr<trie<std::basic_string<char> >, std::default_delete<trie<std::basic_string<char> > > > > > >::emplace(const char&, <brace-enclosed initializer list>)’
children.emplace(it.first, {*it.second});
^
trie.h:90:3: note: candidate is:
In file included from /usr/include/c++/4.8.1/map:61:0,
from trie.h:4,
from main.cpp:2:
/usr/include/c++/4.8.1/bits/stl_map.h:540:2: note: std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::emplace(_Args&& ...) [with _Args = {}; _Key = char; _Tp = std::unique_ptr<trie<std::basic_string<char> >, std::default_delete<trie<std::basic_string<char> > > >; _Compare = std::less<char>; _Alloc = std::allocator<std::pair<const char, std::unique_ptr<trie<std::basic_string<char> >, std::default_delete<trie<std::basic_string<char> > > > > >; typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator = std::_Rb_tree_iterator<std::pair<const char, std::unique_ptr<trie<std::basic_string<char> >, std::default_delete<trie<std::basic_string<char> > > > > >]
emplace(_Args&&... __args)
^
/usr/include/c++/4.8.1/bits/stl_map.h:540:2: note: candidate expects 0 arguments, 2 provided
So my question is:
How do I correctly initialize the map element, the goal being a deep copy of the pointed-to trie, and no needless copies/moves?
Thanks in advance!

By passing {*it.second} as the initialiser for the value, you're effectively trying to initialise a std::unique_ptr<trie<T>> with a trie<T>. I believe you're looking for this:
public:
trie(const trie<T>& other, trie<T>* const parent) :
parent{parent}
{
for(auto const &it : other.children) {
// Separate creation of unique_ptr for exception safety, thanks to #DanielFrey
std::unique_ptr<trie<T>> p(new trie<T>(*it.second));
children.emplace(it.first, std::move(p));
}
}
Note that you will also have to provide a copy constructor, because the default one is deleted, as your class has non-copyable members.
Unrelated to the question, but you should reconsider your design: you most likely have an ownership loop. If a trie<T> stores a unique_ptr to its children and these store a unique_ptr back to their parent, you'll get double deletion errors. Turn one of these (probably the pointer to parent) into a raw pointer. Raw pointers are fine for observing without participating in ownership.

You need
for(auto const &it : other.children) {
std::unique_ptr<trie<T>> element(new trie<T>(*it.second));
children.emplace(it.first, std::move(element));
}
to prevent a resource leak in case an exception is thrown from emplace. If available (C++14), you could simplify the code to
for(auto const &it : other.children) {
children.emplace(it.first, std::make_unique<trie<T>>(*it.second));
}
As a rule of thumb for all smart pointers, you always use std::make_* or you must use a separate line to create each of them.

Related

Inserting in map<string, STRUCT> error

I have a map with the struct defined as under:
struct kv_string {
std::string value;
long long exp_time;
kv_string(const std::string& v): value(v), exp_time(-1) {}
};
Now when I'm trying to insert a new structure using
else if(qargs[0] == "set"){
if(qargs.size()==3){
kv_map.insert(std::make_pair( qargs[1], kv_string(qargs[2])));
}
}
(qargs is a vector<string>), I get the following error:
> In file included from /usr/include/c++/4.8/map:61:0,
> from structures.h:5:
> /usr/include/c++/4.8/bits/stl_map.h: In instantiation of ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key,
> _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = std::basic_string<char>; _Tp = kv_string; _Compare =
> std::less<std::basic_string<char> >; _Alloc =
> std::allocator<std::pair<const std::basic_string<char>, kv_string> >;
> std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = kv_string;
> std::map<_Key, _Tp, _Compare, _Alloc>::key_type =
> std::basic_string<char>]’:
> /usr/include/c++/4.8/stdexcept:281:48: required from here
> /usr/include/c++/4.8/bits/stl_map.h:469:59: error: no matching function for call to ‘kv_string::kv_string()’
> __i = insert(__i, value_type(__k, mapped_type()));
> ^
> /usr/include/c++/4.8/bits/stl_map.h:469:59: note: candidates are:
> structures.h:11:9: note: kv_string::kv_string(const string&)
> kv_string(const std::string& v): value(v), exp_time(-1) {}
> ^
> structures.h:11:9: note: candidate expects 1 argument, 0 provided
> structures.h:8:8: note: kv_string::kv_string(const kv_string&)
> struct kv_string {
> ^
> structures.h:8:8: note: candidate expects 1 argument, 0 provided
> make: *** [server_main.o] Error 1
I have also tried adding an additional constructor kv_string(){}, but it gives a segmentation fault.
You want this:
kv_map.insert(std::make_pair(qargs[1], kv_string(qargs[2]));
Or this:
kv_map.emplace(qargs[1], kv_string(qargs[2]);
Or, in C++17:
kv_map.try_emplace(qargs[1], qargs[2]);
The []-operator default-initializes a new element (if one doesn't exist for the given key), but your type kv_string is not default-constructible. So you cannot use that operator. The above operations are more powerful than the []-operator, too: they return an iterator to the element at the key, and information about whether the key already existed.
The C++ compiler emitted this error message complaining about the lack of a default constructor for your kv_string class:
/usr/include/c++/4.8/bits/stl_map.h:469:59: error: no matching function for call to ‘kv_string::kv_string()’
__i = insert(__i, value_type(__k, mapped_type()));
If you read the documentation for std::map::operator[], you'll see that the mapped type (in your case kv_string) must be default-constructible.
So, if it makes sense for your own design, you could just add a default constructor to your kv_string struct:
struct kv_string {
// ...
// Default constructor
kv_string() : exp_time(-1 /* or whatever default value */) {}
};
As a side note, I would also mark your kv_string(const std::string&) constructor as explicit, to avoid implicit conversions from strings.

error: no matching function for call to 'std::map

typedef struct {
string strDatabaseName;
set <string, greater<string> > setDBAccName;
} UserDBAInfo_t;
typedef struct {
map<int, UserDBAInfo_t > mapUserDBAInfo;
} UserDBInfo_t;
typedef set<string, greater<string> > setNames_t;
int main( int argc, char * argv[] )
{
...
map<string, UserDBInfo_t > mapHRUserDBInfo;
UserDBInfo_t structUserDBInfo;
UserDBAInfo_t structUserDBAInfo;
structUserDBAInfo.strDatabaseName = strDatabaseName;
structUserDBAInfo.setDBAccName.insert(strDBAccName);
structUserDBInfo.mapUserDBAInfo.insert(nDatabaseID, structUserDBAInfo);
mapHRUserDBInfo.insert(make_pair(strSabun, structUserDBInfo)); <--- compile error here
...
}
When I compile it, I got error message.
main.cpp:2778: error: no matching function for call to 'std::map<int, UserDBAInfo_t, std::less<int>, std::allocator<std::pair<const int, UserDBAInfo_t> > >::insert(int&, UserDBAInfo_t&)'
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_map.h:395: note: candidates are: std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const std::pair<const _Key, _Tp>&) [with _Key = int, _Tp = UserDBAInfo_t, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, UserDBAInfo_t> >]
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_map.h:419: note: typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator, const std::pair<const _Key, _Tp>&) [with _Key = int, _Tp = UserDBAInfo_t, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, UserDBAInfo_t> >]
What might be wrong?
The error message, no matching function for call to 'std::map, std::allocator > >::insert(int&, UserDBAInfo_t&), indicates to me that the problem is in the line:
structUserDBInfo.mapUserDBAInfo.insert(nDatabaseID, structUserDBAInfo);
not the line you mentioned in your question. That should be:
structUserDBInfo.mapUserDBAInfo.insert(make_pair(nDatabaseID, structUserDBAInfo));
If you are able to use a C++11 compiler, you can also use:
structUserDBInfo.mapUserDBAInfo.emplace(nDatabaseID, structUserDBAInfo);

Issue with C++ map using member function pointers as keys [duplicate]

This question already has answers here:
C++ Converting function pointer to unique “hash” key
(2 answers)
Closed 9 years ago.
I am writing in C++, trying to compile under Ubuntu, and I am experiencing some issues with a map using function pointers as keys. When I define the map, I get no compiling errors, but as soon as I try to insert an element, I get a rather wordy
In file included from /usr/include/c++/4.6/string:50:0,
from /usr/include/c++/4.6/bits/locale_classes.h:42,
from /usr/include/c++/4.6/bits/ios_base.h:43,
from /usr/include/c++/4.6/ios:43,
from /usr/include/c++/4.6/ostream:40,
from /usr/include/c++/4.6/iostream:40,
from main.cpp:1:
/usr/include/c++/4.6/bits/stl_function.h: In member function ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = int (MyClass::*)()]’:
/usr/include/c++/4.6/bits/stl_tree.h:1277:4: instantiated from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = int (MyClass::*)(), _Val = std::pair<int (MyClass::* const)(), std::vector<int> >, _KeyOfValue = std::_Select1st<std::pair<int (MyClass::* const)(), std::vector<int> > >, _Compare = std::less<int (MyClass::*)()>, _Alloc = std::allocator<std::pair<int (MyClass::* const)(), std::vector<int> > >]’
/usr/include/c++/4.6/bits/stl_map.h:518:41: instantiated from ‘std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::map<_Key, _Tp, _Compare, _Alloc>::value_type>::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const value_type&) [with _Key = int (MyClass::*)(), _Tp = std::vector<int>, _Compare = std::less<int (MyClass::*)()>, _Alloc = std::allocator<std::pair<int (MyClass::* const)(), std::vector<int> > >, typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::map<_Key, _Tp, _Compare, _Alloc>::value_type>::other>::iterator = std::_Rb_tree_iterator<std::pair<int (MyClass::* const)(), std::vector<int> > >, std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<int (MyClass::* const)(), std::vector<int> >]’
main.cpp:36:51: instantiated from here
/usr/include/c++/4.6/bits/stl_function.h:236:22: error: invalid operands of types ‘int (MyClass::* const)()’ and ‘int (MyClass::* const)()’ to binary ‘operator<’
Here is the example that caused the above error message:
#include <iostream>
#include <map>
#include <vector>
// class definition
class MyClass
{
public:
int f1(void);
int f2(void);
};
int MyClass::f1(void)
{
return 1;
}
int MyClass::f2(void)
{
return 2;
}
using namespace std;
int main( int argc, char* argv[] )
{
// define map
map< int (MyClass::*)(void), vector<int> > myMap;
vector<int> myVector;
//myMap[ &MyClass::f1 ] = myVector;
myMap.insert( make_pair( &MyClass::f1, myVector) );
return 0;
}
What could be the issue? I tried with both insert and [] assign, and I get the same error. Browsing the forums, I found this; but could that be the issue? I don't think I need to define an operator "<" for function pointers (shouldn't they behave as regular pointers?) ...or do I?
The error is telling you all you need to know:
invalid operands of types ‘int (MyClass::* const)()’ and ‘int (MyClass::* const)()’ to binary ‘operator<’
You cannot compare member function pointers using standard operator<, so you must provide a custom comparator when declaring your map.
Unfortunately, pointers to member functions cannot be compared for inequality, so you cannot define a comparison operator or use a std::mapin this case. I suggest using std::unordered_map, which only needs a std::hash and equality comparison, which you can do. See here for hashing and here for equality comparison.
You could implement the template specialization for less< int (MyClass::* const)() >, like follows:
typedef int (MyClass::*tMyClassMember)();
namespace std {
template<>
struct less<tMyClassMember>
{
bool operator()(const tMyClassMember& k1, const tMyClassMember& k2) const
{
auto p1 = reinterpret_cast<const intptr_t*>(&k1);
auto p2 = reinterpret_cast<const intptr_t*>(&k2);
return *p1 < *p2;
}
};
}
There may be better ways to compare pointer-to-members than "casting" them to integers, which is an implementation-specific hack, according to this question. That questions contains details about how to do that.

Custom allocator fails for std::map

I'm trying to use custom allocator with C++ STL containers, and it works with vector, but fails with map. Some strange error regarding mmap_allocator<std::_Rb_tree_node<std::pair<const int, int> > > and not using mmap_allocator<std::pair<const int, int> > as I was expecting
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/map:60,
from 4.cpp:2:
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_tree.h: In member function ‘_Alloc std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::get_allocator() const [with _Key = int, _Val = std::pair<const int, int>, _KeyOfValue = std::_Select1st<std::pair<const int, int> >, _Compare = std::less<int>, _Alloc = mmap_allocator<std::pair<const int, int> >]’:
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_tree.h:383: instantiated from ‘void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_destroy_node(std::_Rb_tree_node<_Val>*) [with _Key = int, _Val = std::pair<const int, int>, _KeyOfValue = std::_Select1st<std::pair<const int, int> >, _Compare = std::less<int>, _Alloc = mmap_allocator<std::pair<const int, int> >]’
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_tree.h:972: instantiated from ‘void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_erase(std::_Rb_tree_node<_Val>*) [with _Key = int, _Val = std::pair<const int, int>, _KeyOfValue = std::_Select1st<std::pair<const int, int> >, _Compare = std::less<int>, _Alloc = mmap_allocator<std::pair<const int, int> >]’
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_tree.h:614: instantiated from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::~_Rb_tree() [with _Key = int, _Val = std::pair<const int, int>, _KeyOfValue = std::_Select1st<std::pair<const int, int> >, _Compare = std::less<int>, _Alloc = mmap_allocator<std::pair<const int, int> >]’
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_map.h:87: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_tree.h:354: error: no matching function for call to ‘mmap_allocator<std::pair<const int, int> >::mmap_allocator(const mmap_allocator<std::_Rb_tree_node<std::pair<const int, int> > >&)’
4.cpp:37: note: candidates are: mmap_allocator<T>::mmap_allocator(const mmap_allocator<T>&) [with T = std::pair<const int, int>]
4.cpp:36: note: mmap_allocator<T>::mmap_allocator() [with T = std::pair<const int, int>]
Here is the code:
#include <vector>
#include <map>
#include <stdio.h>
static size_t alloc;
template <typename T>
class mmap_allocator: public std::allocator<T>
{
public:
typedef size_t size_type;
typedef T* pointer;
typedef const T* const_pointer;
template<typename _Tp1>
struct rebind
{
typedef mmap_allocator<_Tp1> other;
};
pointer allocate(size_type n, const void *hint=0)
{
fprintf(stderr, "Alloc %d bytes.\n", n);
alloc += n;
return std::allocator<T>::allocate(n, hint);
}
void deallocate(pointer p, size_type n)
{
fprintf(stderr, "Dealloc %d bytes (%p).\n", n, p);
alloc -= n;
return std::allocator<T>::deallocate(p, n);
}
mmap_allocator() throw(): std::allocator<T>() { fprintf(stderr, "Hello allocator!\n"); }
mmap_allocator(const mmap_allocator &a) throw(): std::allocator<T>(a) { }
~mmap_allocator() throw() { }
};
int main(){
std::vector<int, mmap_allocator<int> > int_vec(1024, 0, mmap_allocator<int>());
std::map<int, int, std::less<int>, mmap_allocator<std::pair<int,int> > > x;
x[1] = 2;
printf("s=%lu\n", alloc);
return 0;
}
Linux, gcc 4.4.6.
I haven't tried fixing it but it seems you haven't defined a constructor which takes an allocator instantiation with a different template argument. That is, you are missing something like
template <typename T>
template <typename O>
mmap_allocator<T>::mmap_allocator(mmap_allocator<O> const& other) {
...
}
From the looks of it, the error stems from trying to construct an allocator type obtained from rebind with some other allocator.

C++ STL:map search by iterator to another map

I'm trying to jump through some hoops to organize data in a special way. I'm including a simplified piece of code that demonstrates my pain.
I can't use boost.
I'm using the latest version of g++ in cygwin.
#include <iostream>
#include <map>
using namespace std;
int main () {
map< int,int > genmap;
map< int,int >::iterator genmapit;
map< map<int,int>::iterator,int > itermap;
// insert something into genmap
genmap.insert (make_pair(1,500) );
// find and return iterator.
genmapit=genmap.find(1);
// insert the iterator/int into itermap. Dies on each of the following 3 versions of this line.
//itermap[genmapit] = 600; // crash
//itermap.insert ( pair< map<int,int>::iterator,int >(genmapit,600) ); // crash
itermap.insert ( make_pair(genmapit,600) ); // crash
return 0;
}
So as you can see, I have 1 simple map, an iterator to that map and another map that has the first argument as an iterator to the first map.
It's clear from this:
Why can't I put an iterator in map?
That I can have an iterator as the second argument. However, the way shown above provides this:
$ make
g++ -c -o main.o main.cpp
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_function.h: In member fun
ction `bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp =
std::_Rb_tree_iterator<std::pair<const int, int> >]':
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_tree.h:871: instantiate
d from `std::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _All
oc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::i
nsert_unique(const _Val&) [with _Key = std::_Rb_tree_iterator<std::pair<const in
t, int> >, _Val = std::pair<const std::_Rb_tree_iterator<std::pair<const int, in
t> >, int>, _KeyOfValue = std::_Select1st<std::pair<const std::_Rb_tree_iterator
<std::pair<const int, int> >, int> >, _Compare = std::less<std::_Rb_tree_iterato
r<std::pair<const int, int> > >, _Alloc = std::allocator<std::pair<const std::_R
b_tree_iterator<std::pair<const int, int> >, int> >]'
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_map.h:360: instantiated
from `std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_
Select1st<std::pair<const _Key, _Tp> >, _Compare, _Alloc>::iterator, bool> std::
map<_Key, _Tp, _Compare, _Alloc>::insert(const std::pair<const _Key, _Tp>&) [wit
h _Key = std::_Rb_tree_iterator<std::pair<const int, int> >, _Tp = int, _Compare
= std::less<std::_Rb_tree_iterator<std::pair<const int, int> > >, _Alloc = std:
:allocator<std::pair<const std::_Rb_tree_iterator<std::pair<const int, int> >, i
nt> >]'
main.cpp:23: instantiated from here
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_function.h:227: error: no
match for 'operator<' in '__x < __y'
make: *** [main.o] Error 1
"instantiated from here" tells me nothing and a web search gives me no info on this.
Does STL:map simply not allow for this? I can recode my app to work around this but it will be very inefficient and I would like to get this working. Is there another kind of pointer I can make for a map element I could use?
Thanks for your time.
You can't do this because std::map iterators are not random access iterators so aren't comparable with <.
Instead, you could use pointers to the value_type in the first map as a map key.
You have to learn to read the error messages. In particular look at the message that comes after the long-winded description where the error happened:
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_function.h:227: error: no
match for 'operator<' in '__x < __y'
Map iterators are not comparable with less-than operator which the map uses by default.
I suppose you can provide a comparison function that compares the pairs pointed to by the iterator, since the iterators themselves cannot be easily compared in a meaningful way.
struct CompareIterator
{
template <class FirstIter, class SecondIter>
bool operator()(FirstIter lhv, SecondIter rhv) const
{
return *lhv < *rhv;
}
};
//usage with map:
map< map<int,int>::iterator,int, CompareIterator > itermap;
std::pair defines operator<. I also used two iterator types, since it might be possible the types are different (iterator and const_iterator)
map<Key, Value>
The map iterator as key element into another map is not possible because map expects operator < to be defined by default to the key. If the Key (in this case map iterator) is not defined then you need to pass a functor as a predicate function that provides the comparison of Key (map iterator).