std::map both costume compare functor and function/ lambda error - c++

I have the following:
inputs:
Map1["Ram"] = 8;
Map1["Aam"] = 8;
Map1["Some"] = 2;
Map1["He"] = 5;
Map1["He"] = 6;
The expected output after insertion to the std::map<std::string, int> should be:
Output:
"Some" 2
"He" 5
"He" 6
"Aam" 8
Please note that:
sorting is according to the values, not keys.
the input Map1["Ram"] = 8; has overwritten by the next input Map1["Aam"] = 8;
Approach 1: Using a functor I was thinking to manage it. I have got this two errors:
||=== Build: Debug in MyTestProgram (compiler: GNU GCC Compiler) ===|
d:\mingw\include\c++\7.3.0\bits\stl_map.h||In instantiation of 'std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](std::map<_Key, _Tp, _Compare, _Alloc>::key_type&&) [with _Key = std::__cxx11::basic_string<char>; _Tp = int; _Compare = compare_functor; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = int; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::__cxx11::basic_string<char>]':|
D:\Programming\C++\CPP Programs\MyTestProgram\MyTestProgram.cpp|22|required from here|
d:\mingw\include\c++\7.3.0\bits\stl_map.h|511|error: no match for call to '(std::map<std::__cxx11::basic_string<char>, int, compare_functor>::key_compare {aka compare_functor}) (std::map<std::__cxx11::basic_string<char>, int, compare_functor>::key_type&, const std::__cxx11::basic_string<char>&)'|
D:\Programming\C++\CPP Programs\MyTestProgram\MyTestProgram.cpp|12|note: candidate: bool compare_functor::operator()(const T&, const T&) const|
D:\Programming\C++\CPP Programs\MyTestProgram\MyTestProgram.cpp|12|note: no known conversion for argument 1 from 'std::map<std::__cxx11::basic_string<char>, int, compare_functor>::key_type {aka std::__cxx11::basic_string<char>}' to 'const T& {aka const std::pair<std::__cxx11::basic_string<char>, int>&}'|
d:\mingw\include\c++\7.3.0\bits\stl_tree.h||In instantiation of 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_lower_bound(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, const _Key&) [with _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, int>; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, int> >; |
d:\mingw\include\c++\7.3.0\bits\stl_tree.h|1187|required from 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::lower_bound(const key_type&) [with _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, int>; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, int> >; _Compare = compare_functor; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> >; std::_Rb_tree<_Key, _Val, _KeyOfVa|
d:\mingw\include\c++\7.3.0\bits\stl_map.h|1234|required from 'std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::lower_bound(const key_type&) [with _Key = std::__cxx11::basic_string<char>; _Tp = int; _Compare = compare_functor; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::__cxx11::basic_string<char>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::__cxx11::basic_string<char|
d:\mingw\include\c++\7.3.0\bits\stl_map.h|509|required from 'std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](std::map<_Key, _Tp, _Compare, _Alloc>::key_type&&) [with _Key = std::__cxx11::basic_string<char>; _Tp = int; _Compare = compare_functor; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = int; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::__cxx11::basic_string<char>]'|
Program.cpp|22|required from here|
d:\mingw\include\c++\7.3.0\bits\stl_tree.h|1872|error: no match for call to '(compare_functor) (const std::__cxx11::basic_string<char>&, const std::__cxx11::basic_string<char>&)'|
Program.cpp|12|note: candidate: bool compare_functor::operator()(const T&, const T&) const|
Program.cpp|12|note: no known conversion for argument 1 from 'const std::__cxx11::basic_string<char>' to 'const T& {aka const std::pair<std::__cxx11::basic_string<char>, int>&}'|
||=== Build failed: 2 error(s), 7 warning(s) (0 minute(s), 0 second(s)) ===|
Approach 2: The same logic I implemented with a lambda and I have got almost the same errors:
||=== Build: Debug in MyTestProgram (compiler: GNU GCC Compiler) ===|
d:\mingw\include\c++\7.3.0\bits\stl_map.h||In instantiation of 'std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](std::map<_Key, _Tp, _Compare, _Alloc>::key_type&&) [with _Key = std::__cxx11::basic_string<char>; _Tp = int; _Compare = bool (*)(const std::pair<std::__cxx11::basic_string<char>, int>&, const std::pair<std::__cxx11::basic_string<char>, int>&); _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = int; std:|
Program.cpp|37|required from here|
d:\mingw\include\c++\7.3.0\bits\stl_map.h|511|error: invalid initialization of reference of type 'const std::pair<std::__cxx11::basic_string<char>, int>&' from expression of type 'std::map<std::__cxx11::basic_string<char>, int, bool (*)(const std::pair<std::__cxx11::basic_string<char>, int>&, const std::pair<std::__cxx11::basic_string<char>, int>&)>::key_type {aka std::__cxx11::basic_string<char>}'|
d:\mingw\include\c++\7.3.0\bits\stl_tree.h||In instantiation of 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_lower_bound(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, const _Key&) [with _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, int>; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, int> >; |
d:\mingw\include\c++\7.3.0\bits\stl_tree.h|1187|required from 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::lower_bound(const key_type&) [with _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, int>; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, int> >; _Compare = bool (*)(const std::pair<std::__cxx11::basic_string<char>, int>&, const std::pair<std::__cxx11::basic_string<char>, int>&); _Alloc = |
d:\mingw\include\c++\7.3.0\bits\stl_map.h|1234|required from 'std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::lower_bound(const key_type&) [with _Key = std::__cxx11::basic_string<char>; _Tp = int; _Compare = bool (*)(const std::pair<std::__cxx11::basic_string<char>, int>&, const std::pair<std::__cxx11::basic_string<char>, int>&); _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::__cxx11::ba|
d:\mingw\include\c++\7.3.0\bits\stl_map.h|509|required from 'std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](std::map<_Key, _Tp, _Compare, _Alloc>::key_type&&) [with _Key = std::__cxx11::basic_string<char>; _Tp = int; _Compare = bool (*)(const std::pair<std::__cxx11::basic_string<char>, int>&, const std::pair<std::__cxx11::basic_string<char>, int>&); _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = int; std::map<_|
Program.cpp|37|required from here|
d:\mingw\include\c++\7.3.0\bits\stl_tree.h|1872|error: invalid initialization of reference of type 'const std::pair<std::__cxx11::basic_string<char>, int>&' from expression of type 'const std::__cxx11::basic_string<char>'|
||=== Build failed: 2 error(s), 7 warning(s) (0 minute(s), 0 second(s)) ===|
I have referred many answers online. But most of them were considering either Key type or Value type while comparing using the functor/ lambda, which was not my case. I would like to compare both Value and Key compared while inserting to the map.
Can anybody explain to me why these implementations fail?
Secondly, what I should have done to get above result while inserting(PS: I would like to still keep string as my key to the map and if it is possible, I do not want any temporary maps to do this result.)?
Here is my code:
#include <iostream>
#include <map>
#include <string>
#include <tuple>
typedef std::pair<std::string, int> T;
typedef bool(*compare_functional_type)(const T&, const T&);
// Way - 1: using functor
struct compare_functor
{
bool operator()(const T& A ,const T& B)const
{
return std::tie(A.second, A.first) < std::tie(B.second, B.first);
// OR in other-words:
//return (A.second == B.second) ? A.first < B.first : A.second < B.second;
};
};
int main()
{
std::map<std::string, int, compare_functor> Map1;
Map1["Ram"] = 8;
Map1["Aam"] = 8;
Map1["Some"] = 2;
Map1["He"] = 5;
Map1["He"] = 6;
// Way - 2: using lambdas and function pointers
compare_functional_type Lambda = [](const T& A, const T& B)
{
return std::tie(A.second, A.first) < std::tie(B.second, B.first);
// OR in other-words:
//return (A.second == B.second) ? A.first < B.first : A.second < B.second;
};
std::map<std::string, int, compare_functional_type> Map2(Lambda);
Map2["Ram"] = 8;
Map2["Aam"] = 8;
Map2["Some"] = 2;
Map2["He"] = 5;
Map2["He"] = 6;
return 0;
}

std::map<int, std::string> is what you want.
To have your inverted syntax, you might use wrapper, something like:
class Wrapper
{
public:
Wrapper(std::map<int, std::string>& m, const std::string& s) : m(m), s(s) {}
void operator =(int k) { m[k] = s; }
private:
std::map<int, std::string>& m;
std::string s;
};
class InvertedMap
{
public:
Wrapper operator[](const std::string& s) { return {m, s}; }
auto begin() const { return m.begin(); }
auto end() const { return m.end(); }
private:
std::map<int, std::string> m;
};
And then:
InvertedMap Map1;
Map1["Ram"] = 8;
Map1["Aam"] = 8;
Map1["Some"] = 2;
Map1["He"] = 5;
Map1["He"] = 6;
for (const auto& p : Map1) {
std::cout << p.second << " " << p.first << std::endl;
}
// Output:
// Some 2
// He 5
// He 6
// Aam 8
Demo

Related

Question about std::make_pair & std::atomic_bool

Why this code snippet does not compile with gcc 4.9.0,
whereas it works well with gcc 12.1.
The same code snippet is compiled with the same option.
Here is the code snippet:
#include<atomic>
#include<thread>
#include<map>
#include<vector>
#include<iostream>
class Demo{
public:
Demo()
{
mp_.insert(std::make_pair(1, true));
mp_.insert(std::make_pair(2, true));
mp_.insert(std::make_pair(3, true));
}
int Get(const int& integer, bool& flag)
{
const auto itr = mp_.find(integer);
if( itr == mp_.end())
{
return -1;
}
else
{
flag = itr->second;
return 0;
}
}
int Set(const int& integer, const bool& flag)
{
const auto itr = mp_.find(integer);
if( itr == mp_.end())
{
return -1;
}
else
{
itr->second = flag;
return 0;
}
}
private:
std::map<int, std::atomic<bool>> mp_;
};
int main()
{
Demo demo;
std::vector<std::thread> vec;
vec.push_back(std::thread([&demo](){
//while(true)
{
for(int i=0; i<9; i++)
{
bool cur_flag = false;
if(demo.Get(i, cur_flag) == 0)
{
demo.Set(i, !cur_flag);
}
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
}));
vec.push_back(std::thread([&demo](){
while(true)
{
for(int i=0; i<9; i++)
{
bool cur_flag = false;
if(demo.Get(i, cur_flag)==0)
{
std::cout << "(" << i << "," << cur_flag <<")" << std::endl;
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
})
);
for(auto& thread:vec)
{
thread.join();
}
}
Here is what gcc 4.9.0 complains:
<source>: In constructor 'Demo::Demo()':
<source>:11:39: error: no matching function for call to 'std::map<int, std::atomic<bool> >::insert(std::pair<int, bool>)'
mp_.insert(std::make_pair(1, true));
^
<source>:11:39: note: candidates are:
In file included from /opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/map:61:0,
from <source>:3:
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:629:7: note: std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const value_type&) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >; typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator = std::_Rb_tree_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const int, std::atomic<bool> >]
insert(const value_type& __x)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:629:7: note: no known conversion for argument 1 from 'std::pair<int, bool>' to 'const value_type& {aka const std::pair<const int, std::atomic<bool> >&}'
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:637:9: note: template<class _Pair, class> std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(_Pair&&) [with _Pair = _Pair; <template-parameter-2-2> = <template-parameter-1-2>; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
insert(_Pair&& __x)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:637:9: note: template argument deduction/substitution failed:
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:633:32: error: no type named 'type' in 'struct std::enable_if<false, void>'
template<typename _Pair, typename = typename
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:650:7: note: void std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::initializer_list<std::pair<const _Key, _Tp> >) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
insert(std::initializer_list<value_type> __list)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:650:7: note: no known conversion for argument 1 from 'std::pair<int, bool>' to 'std::initializer_list<std::pair<const int, std::atomic<bool> > >'
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:679:7: note: std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, const value_type&) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const int, std::atomic<bool> >]
insert(const_iterator __position, const value_type& __x)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:679:7: note: candidate expects 2 arguments, 1 provided
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:690:9: note: template<class _Pair, class> std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, _Pair&&) [with _Pair = _Pair; <template-parameter-2-2> = <template-parameter-1-2>; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
insert(const_iterator __position, _Pair&& __x)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:690:9: note: template argument deduction/substitution failed:
<source>:11:39: note: cannot convert 'std::make_pair<int, bool>((* &1), (* & true))' (type 'std::pair<int, bool>') to type 'std::map<int, std::atomic<bool> >::const_iterator {aka std::_Rb_tree_const_iterator<std::pair<const int, std::atomic<bool> > >}'
mp_.insert(std::make_pair(1, true));
^
In file included from /opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/map:61:0,
from <source>:3:
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:705:9: note: template<class _InputIterator> void std::map<_Key, _Tp, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _InputIterator = _InputIterator; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
insert(_InputIterator __first, _InputIterator __last)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:705:9: note: template argument deduction/substitution failed:
<source>:11:39: note: candidate expects 2 arguments, 1 provided
mp_.insert(std::make_pair(1, true));
^
<source>:12:39: error: no matching function for call to 'std::map<int, std::atomic<bool> >::insert(std::pair<int, bool>)'
mp_.insert(std::make_pair(2, true));
^
<source>:12:39: note: candidates are:
In file included from /opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/map:61:0,
from <source>:3:
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:629:7: note: std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const value_type&) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >; typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator = std::_Rb_tree_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const int, std::atomic<bool> >]
insert(const value_type& __x)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:629:7: note: no known conversion for argument 1 from 'std::pair<int, bool>' to 'const value_type& {aka const std::pair<const int, std::atomic<bool> >&}'
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:637:9: note: template<class _Pair, class> std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(_Pair&&) [with _Pair = _Pair; <template-parameter-2-2> = <template-parameter-1-2>; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
insert(_Pair&& __x)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:637:9: note: template argument deduction/substitution failed:
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:633:32: error: no type named 'type' in 'struct std::enable_if<false, void>'
template<typename _Pair, typename = typename
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:650:7: note: void std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::initializer_list<std::pair<const _Key, _Tp> >) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
insert(std::initializer_list<value_type> __list)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:650:7: note: no known conversion for argument 1 from 'std::pair<int, bool>' to 'std::initializer_list<std::pair<const int, std::atomic<bool> > >'
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:679:7: note: std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, const value_type&) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const int, std::atomic<bool> >]
insert(const_iterator __position, const value_type& __x)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:679:7: note: candidate expects 2 arguments, 1 provided
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:690:9: note: template<class _Pair, class> std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, _Pair&&) [with _Pair = _Pair; <template-parameter-2-2> = <template-parameter-1-2>; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
insert(const_iterator __position, _Pair&& __x)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:690:9: note: template argument deduction/substitution failed:
<source>:12:39: note: cannot convert 'std::make_pair<int, bool>((* &2), (* & true))' (type 'std::pair<int, bool>') to type 'std::map<int, std::atomic<bool> >::const_iterator {aka std::_Rb_tree_const_iterator<std::pair<const int, std::atomic<bool> > >}'
mp_.insert(std::make_pair(2, true));
^
In file included from /opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/map:61:0,
from <source>:3:
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:705:9: note: template<class _InputIterator> void std::map<_Key, _Tp, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _InputIterator = _InputIterator; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
insert(_InputIterator __first, _InputIterator __last)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:705:9: note: template argument deduction/substitution failed:
<source>:12:39: note: candidate expects 2 arguments, 1 provided
mp_.insert(std::make_pair(2, true));
^
<source>:13:39: error: no matching function for call to 'std::map<int, std::atomic<bool> >::insert(std::pair<int, bool>)'
mp_.insert(std::make_pair(3, true));
^
<source>:13:39: note: candidates are:
In file included from /opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/map:61:0,
from <source>:3:
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:629:7: note: std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const value_type&) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >; typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator = std::_Rb_tree_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const int, std::atomic<bool> >]
insert(const value_type& __x)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:629:7: note: no known conversion for argument 1 from 'std::pair<int, bool>' to 'const value_type& {aka const std::pair<const int, std::atomic<bool> >&}'
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:637:9: note: template<class _Pair, class> std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(_Pair&&) [with _Pair = _Pair; <template-parameter-2-2> = <template-parameter-1-2>; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
insert(_Pair&& __x)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:637:9: note: template argument deduction/substitution failed:
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:633:32: error: no type named 'type' in 'struct std::enable_if<false, void>'
template<typename _Pair, typename = typename
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:650:7: note: void std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::initializer_list<std::pair<const _Key, _Tp> >) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
insert(std::initializer_list<value_type> __list)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:650:7: note: no known conversion for argument 1 from 'std::pair<int, bool>' to 'std::initializer_list<std::pair<const int, std::atomic<bool> > >'
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:679:7: note: std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, const value_type&) [with _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const int, std::atomic<bool> > >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const int, std::atomic<bool> >]
insert(const_iterator __position, const value_type& __x)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:679:7: note: candidate expects 2 arguments, 1 provided
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:690:9: note: template<class _Pair, class> std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, _Pair&&) [with _Pair = _Pair; <template-parameter-2-2> = <template-parameter-1-2>; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
insert(const_iterator __position, _Pair&& __x)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:690:9: note: template argument deduction/substitution failed:
<source>:13:39: note: cannot convert 'std::make_pair<int, bool>((* &3), (* & true))' (type 'std::pair<int, bool>') to type 'std::map<int, std::atomic<bool> >::const_iterator {aka std::_Rb_tree_const_iterator<std::pair<const int, std::atomic<bool> > >}'
mp_.insert(std::make_pair(3, true));
^
In file included from /opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/map:61:0,
from <source>:3:
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:705:9: note: template<class _InputIterator> void std::map<_Key, _Tp, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _InputIterator = _InputIterator; _Key = int; _Tp = std::atomic<bool>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::atomic<bool> > >]
insert(_InputIterator __first, _InputIterator __last)
^
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/bits/stl_map.h:705:9: note: template argument deduction/substitution failed:
<source>:13:39: note: candidate expects 2 arguments, 1 provided
mp_.insert(std::make_pair(3, true));
^
Could somebody shed some light on the reason lies behind it?
A reduced example is this:
struct destination_t {
destination_t(int) {}
destination_t(const destination_t&) = delete;
};
static_assert(std::is_constructible<
std::pair<const int, destination_t>,
std::pair<int, int>
>::value, "");
map::insert is trying to call this converting constructor. The behavior changed in GCC 6.
This is N4387. See change 6. Previously, this constructor had:
This constructor shall not participate in overload resolution unless U is implicitly convertible to first_type and V is implicitly convertible to second_type.
That changed to:
This constructor shall not participate in overload resolution unless is_constructible<first_type, U&&>::value is true and is_constructible<second_type, V&&>::value is true.
The GCC commit is here.
This was applied as a DR, so it changed in all standards modes.

Overloading && for `std::variant` breaks an unrelated `std::map`

(This question was originally asked by a different user at Russian SO. I'm reposting it here with minor changes to give it more exposure.)
Consider this code:
#include <map>
#include <variant>
void operator&&(std::variant<int>, std::variant<int>) {}
int main()
{
std::map<int, int> vals;
vals.find(42);
}
Clang (with both libstdc++ and libc++) and MSVC compile it without problems.
Hovewer, GCC 11.1 and newer (including trunk) give this: Run on gcc.godbolt.org
In file included from /opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/move.h:57,
from /opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/stl_pair.h:59,
from /opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/stl_algobase.h:64,
from /opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/stl_tree.h:63,
from /opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/map:60,
from <source>:1:
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/type_traits: In instantiation of 'struct std::is_invocable<const std::less<int>&, const int&, const int&>':
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/type_traits:3001:73: required from 'constexpr const bool std::is_invocable_v<const std::less<int>&, const int&, const int&>'
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/stl_tree.h:770:8: required from 'static const _Key& std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_S_key(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type) [with _Key = int; _Val = std::pair<const int, int>; _KeyOfValue = std::_Select1st<std::pair<const int, int> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type = const std::_Rb_tree_node<std::pair<const int, int> >*]'
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/stl_tree.h:1903:36: required from 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_lower_bound(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, const _Key&) [with _Key = int; _Val = std::pair<const int, int>; _KeyOfValue = std::_Select1st<std::pair<const int, int> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree<int, std::pair<const int, int>, std::_Select1st<std::pair<const int, int> >, std::less<int>, std::allocator<std::pair<const int, int> > >::iterator; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const int, int> >*; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr = std::_Rb_tree_node_base*]'
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/stl_tree.h:2521:36: required from 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::find(const _Key&) [with _Key = int; _Val = std::pair<const int, int>; _KeyOfValue = std::_Select1st<std::pair<const int, int> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree<int, std::pair<const int, int>, std::_Select1st<std::pair<const int, int> >, std::less<int>, std::allocator<std::pair<const int, int> > >::iterator]'
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/stl_map.h:1170:25: required from 'std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::find(const key_type&) [with _Key = int; _Tp = int; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree<int, std::pair<const int, int>, std::_Select1st<std::pair<const int, int> >, std::less<int>, std::allocator<std::pair<const int, int> > >::iterator; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]'
<source>:9:14: required from here
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/type_traits:2942:7: error: ambiguous overload for 'operator&&' (operand types are 'std::true_type' {aka 'std::integral_constant<bool, true>'} and 'std::true_type' {aka 'std::integral_constant<bool, true>'})
2942 | static_assert((std::__is_complete_or_unbounded(
| ^~~~~~~~~~~~~
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/type_traits:2942:7: note: candidate: 'operator&&(std::integral_constant<bool, true>::value_type {aka bool}, std::integral_constant<bool, true>::value_type {aka bool})' (built-in)
<source>:4:6: note: candidate: 'void operator&&(std::variant<int>, std::variant<int>)'
4 | void operator &&(std::variant<int>, std::variant<int>) {}
| ^~~~~~~~
What's going on here?
EDIT:
Our operator== overload should be invisible for name lookup from <variant> (except for ADL, which is not involved here), so this is definitely a GCC bug.
#rustyx found GCC bug #51577, which looks very similar. But there's more to it, because that bug was introduced in GCC 4.7.0, while the code above only breaks and 11.1 and newer.
This was a GCC bug, fixed in GCC 12.

Error using custom comparator for sorting map

I'm trying to sort the keys of a Sparse Matrix by row and column, and I want to use a map for this purpose. I added a custom comparator to ensure that, but I facing the following compilation error:
g++ -O2 -Wall -std=c++11 -Wextra -Wpedantic -c -o main.o main.cpp
In file included from /usr/include/c++/9/map:60,
from Matrix.hh:1,
from main.cpp:3:
/usr/include/c++/9/bits/stl_tree.h: In instantiation of ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::find(const _Key&) const [with _Key = std::pair<int, int>; _Val = std::pair<const std::pair<int, int>, int>; _KeyOfValue = std::_Select1st<std::pair<const std::pair<int, int>, int> >; _Compare = compare_keys; _Alloc = std::allocator<std::pair<const std::pair<int, int>, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const std::pair<int, int>, int> >]’:
/usr/include/c++/9/bits/stl_map.h:1215:31: required from ‘std::map<_Key, _Tp, _Compare, _Alloc>::size_type std::map<_Key, _Tp, _Compare, _Alloc>::count(const key_type&) const [with _Key = std::pair<int, int>; _Tp = int; _Compare = compare_keys; _Alloc = std::allocator<std::pair<const std::pair<int, int>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::size_type = long unsigned int; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::pair<int, int>]’
Matrix.hh:23:9: required from ‘bool Matrix<T>::emplace(int, int, T) [with T = int]’
main.cpp:7:5: required from here
/usr/include/c++/9/bits/stl_tree.h:2572:8: error: no match for call to ‘(const compare_keys) (const std::pair<int, int>&, const std::pair<int, int>&)’
2571 | return (__j == end()
| ~~~~~~~~~~~~~
2572 | || _M_impl._M_key_compare(__k,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2573 | _S_key(__j._M_node))) ? end() : __j;
| ~~~~~~~~~~~~~~~~~~~~~
In file included from main.cpp:3:
Matrix.hh:6:10: note: candidate: ‘bool compare_keys::operator()(const key&, const key&)’ <near match>
6 | bool operator() (const key& left_key, const key& right_key) {
| ^~~~~~~~
Matrix.hh:6:10: note: passing ‘const compare_keys*’ as ‘this’ argument discards qualifiers
In file included from /usr/include/c++/9/map:60,
from Matrix.hh:1,
from main.cpp:3:
/usr/include/c++/9/bits/stl_tree.h: In instantiation of ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_lower_bound(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Base_ptr, const _Key&) const [with _Key = std::pair<int, int>; _Val = std::pair<const std::pair<int, int>, int>; _KeyOfValue = std::_Select1st<std::pair<const std::pair<int, int>, int> >; _Compare = compare_keys; _Alloc = std::allocator<std::pair<const std::pair<int, int>, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const std::pair<int, int>, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type = const std::_Rb_tree_node<std::pair<const std::pair<int, int>, int> >*; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Base_ptr = const std::_Rb_tree_node_base*]’:
/usr/include/c++/9/bits/stl_tree.h:2570:22: required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::find(const _Key&) const [with _Key = std::pair<int, int>; _Val = std::pair<const std::pair<int, int>, int>; _KeyOfValue = std::_Select1st<std::pair<const std::pair<int, int>, int> >; _Compare = compare_keys; _Alloc = std::allocator<std::pair<const std::pair<int, int>, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const std::pair<int, int>, int> >]’
/usr/include/c++/9/bits/stl_map.h:1215:31: required from ‘std::map<_Key, _Tp, _Compare, _Alloc>::size_type std::map<_Key, _Tp, _Compare, _Alloc>::count(const key_type&) const [with _Key = std::pair<int, int>; _Tp = int; _Compare = compare_keys; _Alloc = std::allocator<std::pair<const std::pair<int, int>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::size_type = long unsigned int; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::pair<int, int>]’
Matrix.hh:23:9: required from ‘bool Matrix<T>::emplace(int, int, T) [with T = int]’
main.cpp:7:5: required from here
/usr/include/c++/9/bits/stl_tree.h:1945:6: error: no match for call to ‘(const compare_keys) (const std::pair<int, int>&, const std::pair<int, int>&)’
1945 | if (!_M_impl._M_key_compare(_S_key(__x), __k))
In file included from main.cpp:3:
Matrix.hh:6:10: note: candidate: ‘bool compare_keys::operator()(const key&, const key&)’ <near match>
6 | bool operator() (const key& left_key, const key& right_key) {
| ^~~~~~~~
Matrix.hh:6:10: note: passing ‘const compare_keys*’ as ‘this’ argument discards qualifiers
The Matrix class:
#include <map>
#include <iostream>
typedef std::pair<int,int> key;
struct compare_keys {
bool operator() (const key& left_key, const key& right_key) {
if (left_key.first < right_key.first) return true;
if (left_key.first > right_key.first) return false;
return left_key.second > right_key.second;
}
};
template <typename T>
class Matrix {
private:
//Sparse matrix representation
std::map<key, T, compare_keys> values;
int max_row, max_col;
public:
Matrix() : max_row(0), max_col(0) {};
Matrix(int rows, int cols) : max_row(rows), max_col(cols) {};
bool emplace(int row, int col, T value) {
if (this->values.count(std::make_pair(row, col)))
return false;
this->values[std::make_pair(row, col)] = value;
if (row > max_row) max_row = row;
if (col > max_col) max_col = col;
return true;
}
};
I don't see why the compare_keys operator doesn't match the comparator in the map constructor.
You are missing const.
bool operator() (const key& left_key, const key& right_key) const {
^^^^^

required from 'std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique

I'm getting a compilation error,
required from 'std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(_Arg&&) [with _Arg = Solution::EnhancedNode* const&; _Key = Solution::EnhancedNode*; _Val = Solution::EnhancedNode*; _KeyOfValue = std::_Identity<Solution::EnhancedNode*>; _Compare = Solution::EnhancedNodeComparator; _Alloc = std::allocator<Solution::EnhancedNode*>]'
Unfortunately there is no line number, but my removing sections of code, I believe it has something to do with an std::set that I want to apply a custom comparator to:
class EnhancedNode {
public:
EnhancedNode(TreeNode* node) {
node_ = node;
distance_ = numeric_limits<double>::max();
discarded_ = false;
}
TreeNode* node_;
double distance_;
bool discarded_;
};
struct EnhancedNodeComparator {
bool operator() (const EnhancedNode*& a, const EnhancedNode*& b) const {
return a->distance_ < b->distance_;
}
};
set<EnhancedNode*, EnhancedNodeComparator> closest_;
set<EnhancedNode*, EnhancedNodeComparator> next_;
Am I doing anything obviously wrong?
The comparator of std::set should definitely accept references to the const qualified type which is in the set.
What you got wrong is the qualification of the type in the set. It's EnhancedNode*, so qualifying it with const should give EnhancedNode* const. And not const EnhancedNode*.
This is once again a case of leading const being misleading. Change your original comparator, with reference and all, to this:
struct EnhancedNodeComparator {
bool operator() (EnhancedNode const * const& a, EnhancedNode const * const& b) const {
return a->distance_ < b->distance_;
}
};
You can keep the const-qualified pointee, as well. Since C++ explicitly allows it.
The reason that your issue was fixed when you got rid of the reference, is that top-level const is ignored when passing by value. So it didn't matter the the pointer your function received as an argument wasn't const qualified. It was just a copy of the original.
While creating a Minimal, Complete, VerifiableTM example, I was able to solve my problem. I'm posting it anyway because Google surprisingly had zero hits for the first portions of my error in quotes.
Turns out I didn't need the &s in
struct EnhancedNodeComparator {
bool operator() (const EnhancedNode*& a, const EnhancedNode*& b) const {
I found this out by compiling on a different compiler, http://cpp.sh,
#include <limits>
#include <set>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
class EnhancedNode {
public:
EnhancedNode(TreeNode* node) {
node_ = node;
distance_ = numeric_limits<double>::max();
discarded_ = false;
}
TreeNode* node_;
double distance_;
bool discarded_;
};
struct EnhancedNodeComparator {
bool operator() (const EnhancedNode*& a, const EnhancedNode*& b) const {
return a->distance_ < b->distance_;
}
};
int main()
{
set<EnhancedNode*, EnhancedNodeComparator> closest_;
closest_.insert(new EnhancedNode(new TreeNode(1)));
return 0;
}
and getting a more helpful error:
In file included from /usr/include/c++/4.9/set:60:0,
from 3:
/usr/include/c++/4.9/bits/stl_tree.h: In instantiation of 'std::pair<std::_Rb_tree_node_base*, std::_Rb_tree_node_base*> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_get_insert_unique_pos(const key_type&) [with _Key = EnhancedNode*; _Val = EnhancedNode*; _KeyOfValue = std::_Identity<EnhancedNode*>; _Compare = EnhancedNodeComparator; _Alloc = std::allocator<EnhancedNode*>; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::key_type = EnhancedNode*]':
/usr/include/c++/4.9/bits/stl_tree.h:1498:47: required from 'std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(_Arg&&) [with _Arg = EnhancedNode*; _Key = EnhancedNode*; _Val = EnhancedNode*; _KeyOfValue = std::_Identity<EnhancedNode*>; _Compare = EnhancedNodeComparator; _Alloc = std::allocator<EnhancedNode*>]'
/usr/include/c++/4.9/bits/stl_set.h:511:40: required from 'std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(std::set<_Key, _Compare, _Alloc>::value_type&&) [with _Key = EnhancedNode*; _Compare = EnhancedNodeComparator; _Alloc = std::allocator<EnhancedNode*>; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator = std::_Rb_tree_const_iterator<EnhancedNode*>; std::set<_Key, _Compare, _Alloc>::value_type = EnhancedNode*]'
33:54: required from here
/usr/include/c++/4.9/bits/stl_tree.h:1445:11: error: no match for call to '(EnhancedNodeComparator) (EnhancedNode* const&, EnhancedNode* const&)'
__comp = _M_impl._M_key_compare(__k, _S_key(__x));
^
24:8: note: candidate is:
25:10: note: bool EnhancedNodeComparator::operator()(const EnhancedNode*&, const EnhancedNode*&) const
25:10: note: no known conversion for argument 1 from 'const key_type {aka EnhancedNode* const}' to 'const EnhancedNode*&'
In file included from /usr/include/c++/4.9/set:60:0,
from 3:
/usr/include/c++/4.9/bits/stl_tree.h:1456:7: error: no match for call to '(EnhancedNodeComparator) (EnhancedNode* const&, EnhancedNode* const&)'
if (_M_impl._M_key_compare(_S_key(__j._M_node), __k))
^
24:8: note: candidate is:
25:10: note: bool EnhancedNodeComparator::operator()(const EnhancedNode*&, const EnhancedNode*&) const
25:10: note: no known conversion for argument 1 from 'EnhancedNode* const' to 'const EnhancedNode*&'
In file included from /usr/include/c++/4.9/set:60:0,
from 3:
/usr/include/c++/4.9/bits/stl_tree.h: In instantiation of 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, _Arg&&) [with _Arg = EnhancedNode*; _Key = EnhancedNode*; _Val = EnhancedNode*; _KeyOfValue = std::_Identity<EnhancedNode*>; _Compare = EnhancedNodeComparator; _Alloc = std::allocator<EnhancedNode*>; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<EnhancedNode*>; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr = std::_Rb_tree_node_base*]':
/usr/include/c++/4.9/bits/stl_tree.h:1502:38: required from 'std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(_Arg&&) [with _Arg = EnhancedNode*; _Key = EnhancedNode*; _Val = EnhancedNode*; _KeyOfValue = std::_Identity<EnhancedNode*>; _Compare = EnhancedNodeComparator; _Alloc = std::allocator<EnhancedNode*>]'
/usr/include/c++/4.9/bits/stl_set.h:511:40: required from 'std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(std::set<_Key, _Compare, _Alloc>::value_type&&) [with _Key = EnhancedNode*; _Compare = EnhancedNodeComparator; _Alloc = std::allocator<EnhancedNode*>; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator = std::_Rb_tree_const_iterator<EnhancedNode*>; std::set<_Key, _Compare, _Alloc>::value_type = EnhancedNode*]'
33:54: required from here
/usr/include/c++/4.9/bits/stl_tree.h:1140:8: error: no match for call to '(EnhancedNodeComparator) (EnhancedNode*&, EnhancedNode* const&)'
|| _M_impl._M_key_compare(_KeyOfValue()(__v),
^
24:8: note: candidate is:
25:10: note: bool EnhancedNodeComparator::operator()(const EnhancedNode*&, const EnhancedNode*&) const
25:10: note: no known conversion for argument 1 from 'EnhancedNode*' to 'const EnhancedNode*&'
I don't really understand why this is so. All the examples for custom comparators for std::set I found online seemed to add &. If someone could explain as an answer, I would select it as the complete answer.

c++11, why does this unordered_map defined for vector <int> not work?

I am trying to create an unordered_map<vector<int>, int>. I know that I need to have my own hash function, so I tried to build one. I am capable of creating it and compiling it fine, but I get compilation errors when I try to access it.
Here is the code:
#include <bits/stdc++.h>
using namespace std;
class mhash {
public:
std::size_t operator()(std::vector<int> const& vec) const {
std::size_t seed = vec.size();
for(auto& i : vec) {
seed ^= i + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
return seed;
}
};
map <vector <int>,int, mhash> M;
int main(){
vector <int> V;
M[V]=5;
cout << M[V];
}
I am compiling using g++ -std=c++11.
If I only declare the unordered_map it compiles fine, but when I try to use it I get the following errors:
In file included from /usr/include/c++/5/map:61:0,
from /usr/include/x86_64-linux-gnu/c++/5/bits/stdc++.h:80,
from exp.cpp:1:
/usr/include/c++/5/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::vector<int>; _Tp = int; _Compare = mhash; _Alloc = std::allocator<std::pair<const std::vector<int>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = int; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::vector<int>]’:
exp.cpp:19:5: required from here
/usr/include/c++/5/bits/stl_map.h:481:32: error: no match for call to ‘(std::map<std::vector<int>, int, mhash>::key_compare {aka mhash}) (const key_type&, const std::vector<int>&)’
if (__i == end() || key_comp()(__k, (*__i).first))
^
exp.cpp:6:15: note: candidate: std::size_t mhash::operator()(const std::vector<int>&) const
std::size_t operator()(std::vector<int> const& vec) const {
^
exp.cpp:6:15: note: candidate expects 1 argument, 2 provided
In file included from /usr/include/c++/5/map:60:0,
from /usr/include/x86_64-linux-gnu/c++/5/bits/stdc++.h:80,
from exp.cpp:1:
/usr/include/c++/5/bits/stl_tree.h: In instantiation of ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_lower_bound(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type, const _Key&) [with _Key = std::vector<int>; _Val = std::pair<const std::vector<int>, int>; _KeyOfValue = std::_Select1st<std::pair<const std::vector<int>, int> >; _Compare = mhash; _Alloc = std::allocator<std::pair<const std::vector<int>, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::vector<int>, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::vector<int>, int> >*]’:
/usr/include/c++/5/bits/stl_tree.h:1091:30: required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::lower_bound(const key_type&) [with _Key = std::vector<int>; _Val = std::pair<const std::vector<int>, int>; _KeyOfValue = std::_Select1st<std::pair<const std::vector<int>, int> >; _Compare = mhash; _Alloc = std::allocator<std::pair<const std::vector<int>, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::vector<int>, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::key_type = std::vector<int>]’
/usr/include/c++/5/bits/stl_map.h:916:36: required from ‘std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::lower_bound(const key_type&) [with _Key = std::vector<int>; _Tp = int; _Compare = mhash; _Alloc = std::allocator<std::pair<const std::vector<int>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::vector<int>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::vector<int>]’
/usr/include/c++/5/bits/stl_map.h:479:28: required from ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = std::vector<int>; _Tp = int; _Compare = mhash; _Alloc = std::allocator<std::pair<const std::vector<int>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = int; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::vector<int>]’
exp.cpp:19:5: required from here
/usr/include/c++/5/bits/stl_tree.h:1628:6: error: no match for call to ‘(mhash) (const std::vector<int>&, const std::vector<int>&)’
if (!_M_impl._M_key_compare(_S_key(__x), __k))
^
exp.cpp:6:15: note: candidate: std::size_t mhash::operator()(const std::vector<int>&) const
std::size_t operator()(std::vector<int> const& vec) const {
^
exp.cpp:6:15: note: candidate expects 1 argument, 2 provided
You wrote map, not unordered_map.
But... if you want a map:
The third template argument for a map is not a hash, but a comparator.
bool operator()(a, b)
Because you instantiated a std::map, not an std::unordered_map.
Normal maps don't take hash functions.
Presumably this is just a typo.
By the way, avoid #include <bits/stdc++.h>.