Related
(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.
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
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>.
I got this example about implementing generic memoization in C++. However, as someone made notice in this comment, the original code makes 2 lookups, while the code below makes only one.
The only problem is that there is an error at the second return that I don't understand.
template <typename ReturnType, typename... Args>
std::function<ReturnType (Args...)> memoize(std::function<ReturnType (Args...)> func)
{
std::map<std::tuple<Args...>, ReturnType> cache;
return ([=](Args... args) mutable {
std::tuple<Args...> t(args...);
auto range = cache.equal_range(t);
if (range.first != range.second) return (*range.first).second;
return (*cache.insert(range.first, func(args...))).second;
});
}
Compiler error:
In instantiation of 'memoize(std::function<_Res(_ArgTypes ...)>)::<lambda(Args ...)> mutable [with ReturnType = int; Args = {int, int}]':
14:36: required from 'struct memoize(std::function<_Res(_ArgTypes ...)>) [with ReturnType = int; Args = {int, int}]::<lambda(int, int)>'
16:6: required from 'std::function<_Res(_ArgTypes ...)> memoize(std::function<_Res(_ArgTypes ...)>) [with ReturnType = int; Args = {int, int}]'
34:56: required from here
14:9: error: no matching function for call to 'std::map<std::tuple<int, int>, int, std::less<std::tuple<int, int> >, std::allocator<std::pair<const std::tuple<int, int>, int> > >::insert(std::_Rb_tree_iterator<std::pair<const std::tuple<int, int>, int> >&, int)'
14:9: note: candidates are:
In file included from /usr/include/c++/4.9/map:61:0,
from 1:
/usr/include/c++/4.9/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<_Alloc>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const value_type&) [with _Key = std::tuple<int, int>; _Tp = int; _Compare = std::less<std::tuple<int, int> >; _Alloc = std::allocator<std::pair<const std::tuple<int, int>, int> >; typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<std::pair<const _Key, _Tp> >::other>::iterator = std::_Rb_tree_iterator<std::pair<const std::tuple<int, int>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const std::tuple<int, int>, int>]
insert(const value_type& __x)
^
/usr/include/c++/4.9/bits/stl_map.h:629:7: note: candidate expects 1 argument, 2 provided
/usr/include/c++/4.9/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<_Alloc>::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 = std::tuple<int, int>; _Tp = int; _Compare = std::less<std::tuple<int, int> >; _Alloc = std::allocator<std::pair<const std::tuple<int, int>, int> >]
insert(_Pair&& __x)
^
/usr/include/c++/4.9/bits/stl_map.h:637:9: note: template argument deduction/substitution failed:
14:9: note: candidate expects 1 argument, 2 provided
In file included from /usr/include/c++/4.9/map:61:0,
from 1:
/usr/include/c++/4.9/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 = std::tuple<int, int>; _Tp = int; _Compare = std::less<std::tuple<int, int> >; _Alloc = std::allocator<std::pair<const std::tuple<int, int>, int> >]
insert(std::initializer_list<value_type> __list)
^
/usr/include/c++/4.9/bits/stl_map.h:650:7: note: candidate expects 1 argument, 2 provided
/usr/include/c++/4.9/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 = std::tuple<int, int>; _Tp = int; _Compare = std::less<std::tuple<int, int> >; _Alloc = std::allocator<std::pair<const std::tuple<int, int>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::tuple<int, int>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const std::tuple<int, int>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const std::tuple<int, int>, int>]
insert(const_iterator __position, const value_type& __x)
^
/usr/include/c++/4.9/bits/stl_map.h:679:7: note: no known conversion for argument 2 from 'int' to 'const value_type& {aka const std::pair<const std::tuple<int, int>, int>&}'
/usr/include/c++/4.9/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 = std::tuple<int, int>; _Tp = int; _Compare = std::less<std::tuple<int, int> >; _Alloc = std::allocator<std::pair<const std::tuple<int, int>, int> >]
insert(const_iterator __position, _Pair&& __x)
^
/usr/include/c++/4.9/bits/stl_map.h:690:9: note: template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/stl_map.h:686:32: error: no type named 'type' in 'struct std::enable_if<false, void>'
template<typename _Pair, typename = typename
^
/usr/include/c++/4.9/bits/stl_map.h:705:9: note: template<class _InputIterator> void std::map<_Key, _Tp, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _InputIterator = _InputIterator; _Key = std::tuple<int, int>; _Tp = int; _Compare = std::less<std::tuple<int, int> >; _Alloc = std::allocator<std::pair<const std::tuple<int, int>, int> >]
insert(_InputIterator __first, _InputIterator __last)
^
The error is inside your lambda:
auto range = cache.equal_range(t);
...
... cache.insert(range.first, func(args...)) ...
and is
14:9: error: no matching function for call to
'std::map<std::tuple<int, int>, int,...>
::insert(std::_Rb_tree_iterator<...>&, int)'
It's telling you that you're calling insert wrongly.
The range returned from equal_range is a pair of iterators - you need to dereference the first iterator and take the first (key) element, to get the key/value pair you want. That is, something like
cache.insert(range.first, make_pair(t, func(args...)))
In general, you can help yourself figure these errors out by:
simplifying your code (these big compound statements mean lots of things are happening, and there's lots of potential errors, on a single line),
by reading the error message carefully (it does list the column, and does say the problem is with insert,
and if all else fails by reproducing the error in a minimal example (removing code unrelated to the error reduces the number of issues to consider).
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);