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.
Related
I want to use a std::map with certain types of functions (certain, specific parameter types) as possible values. However, the following (minimal) example does not compile.
Why is that and how can I allow FunctionType<bool> and FunctionType<int> as possible values for the Map?
#include <functional>
#include <iostream>
#include <map>
#include <string>
#include <variant>
template <typename T>
using FunctionType = std::function<T(T)>;
int main()
{
auto myMap = std::map<std::string, std::variant<FunctionType<bool>, FunctionType<int>>>
{
{"foo", [](bool x){return x;}},
{"bar", [](int x){return x;}},
};
return 0;
}
Error message:
$ g++ --std=c++2a -o /tmp/variant-test /tmp/variant-test.cpp && /tmp/variant-test
variant-test.cpp: In function ‘int main()’:
variant-test.cpp:18:5: error: no matching function for call to ‘std::map<std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > >::map(<brace-enclosed initializer list>)’
18 | };
| ^
In file included from /usr/include/c++/10/map:61,
from variant-test.cpp:3:
/usr/include/c++/10/bits/stl_map.h:290:2: note: candidate: ‘template<class _InputIterator> std::map<_Key, _Tp, _Compare, _Alloc>::map(_InputIterator, _InputIterator, const _Compare&, const allocator_type&) [with _InputIterator = _InputIterator; _Key = std::__cxx11::basic_string<char>; _Tp = std::variant<std::function<bool(bool)>, std::function<int(int)> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >]’
290 | map(_InputIterator __first, _InputIterator __last,
| ^~~
/usr/include/c++/10/bits/stl_map.h:290:2: note: template argument deduction/substitution failed:
variant-test.cpp:18:5: note: candidate expects 4 arguments, 2 provided
18 | };
| ^
In file included from /usr/include/c++/10/map:61,
from variant-test.cpp:3:
/usr/include/c++/10/bits/stl_map.h:273:2: note: candidate: ‘template<class _InputIterator> std::map<_Key, _Tp, _Compare, _Alloc>::map(_InputIterator, _InputIterator) [with _InputIterator = _InputIterator; _Key = std::__cxx11::basic_string<char>; _Tp = std::variant<std::function<bool(bool)>, std::function<int(int)> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >]’
273 | map(_InputIterator __first, _InputIterator __last)
| ^~~
/usr/include/c++/10/bits/stl_map.h:273:2: note: template argument deduction/substitution failed:
variant-test.cpp:18:5: note: couldn’t deduce template parameter ‘_InputIterator’
18 | };
| ^
In file included from /usr/include/c++/10/map:61,
from variant-test.cpp:3:
/usr/include/c++/10/bits/stl_map.h:256:2: note: candidate: ‘template<class _InputIterator> std::map<_Key, _Tp, _Compare, _Alloc>::map(_InputIterator, _InputIterator, const allocator_type&) [with _InputIterator = _InputIterator; _Key = std::__cxx11::basic_string<char>; _Tp = std::variant<std::function<bool(bool)>, std::function<int(int)> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >]’
256 | map(_InputIterator __first, _InputIterator __last,
| ^~~
/usr/include/c++/10/bits/stl_map.h:256:2: note: template argument deduction/substitution failed:
variant-test.cpp:18:5: note: candidate expects 3 arguments, 2 provided
18 | };
| ^
In file included from /usr/include/c++/10/map:61,
from variant-test.cpp:3:
/usr/include/c++/10/bits/stl_map.h:250:7: note: candidate: ‘std::map<_Key, _Tp, _Compare, _Alloc>::map(std::initializer_list<std::pair<const _Key, _Tp> >, const allocator_type&) [with _Key = std::__cxx11::basic_string<char>; _Tp = std::variant<std::function<bool(bool)>, std::function<int(int)> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >; std::map<_Key, _Tp, _Compare, _Alloc>::allocator_type = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >]’
250 | map(initializer_list<value_type> __l, const allocator_type& __a)
| ^~~
/usr/include/c++/10/bits/stl_map.h:250:40: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘std::initializer_list<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >’
250 | map(initializer_list<value_type> __l, const allocator_type& __a)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
/usr/include/c++/10/bits/stl_map.h:244:7: note: candidate: ‘std::map<_Key, _Tp, _Compare, _Alloc>::map(std::map<_Key, _Tp, _Compare, _Alloc>&&, const allocator_type&) [with _Key = std::__cxx11::basic_string<char>; _Tp = std::variant<std::function<bool(bool)>, std::function<int(int)> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >; std::map<_Key, _Tp, _Compare, _Alloc>::allocator_type = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >]’
244 | map(map&& __m, const allocator_type& __a)
| ^~~
/usr/include/c++/10/bits/stl_map.h:244:17: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘std::map<std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > >&&’
244 | map(map&& __m, const allocator_type& __a)
| ~~~~~~^~~
/usr/include/c++/10/bits/stl_map.h:240:7: note: candidate: ‘std::map<_Key, _Tp, _Compare, _Alloc>::map(const std::map<_Key, _Tp, _Compare, _Alloc>&, const allocator_type&) [with _Key = std::__cxx11::basic_string<char>; _Tp = std::variant<std::function<bool(bool)>, std::function<int(int)> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >; std::map<_Key, _Tp, _Compare, _Alloc>::allocator_type = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >]’
240 | map(const map& __m, const allocator_type& __a)
| ^~~
/usr/include/c++/10/bits/stl_map.h:240:22: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘const std::map<std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > >&’
240 | map(const map& __m, const allocator_type& __a)
| ~~~~~~~~~~~^~~
/usr/include/c++/10/bits/stl_map.h:236:7: note: candidate: ‘std::map<_Key, _Tp, _Compare, _Alloc>::map(const allocator_type&) [with _Key = std::__cxx11::basic_string<char>; _Tp = std::variant<std::function<bool(bool)>, std::function<int(int)> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >; std::map<_Key, _Tp, _Compare, _Alloc>::allocator_type = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >]’
236 | map(const allocator_type& __a)
| ^~~
/usr/include/c++/10/bits/stl_map.h:236:7: note: candidate expects 1 argument, 2 provided
/usr/include/c++/10/bits/stl_map.h:228:7: note: candidate: ‘std::map<_Key, _Tp, _Compare, _Alloc>::map(std::initializer_list<std::pair<const _Key, _Tp> >, const _Compare&, const allocator_type&) [with _Key = std::__cxx11::basic_string<char>; _Tp = std::variant<std::function<bool(bool)>, std::function<int(int)> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >; std::map<_Key, _Tp, _Compare, _Alloc>::allocator_type = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >]’
228 | map(initializer_list<value_type> __l,
| ^~~
/usr/include/c++/10/bits/stl_map.h:228:40: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘std::initializer_list<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >’
228 | map(initializer_list<value_type> __l,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
/usr/include/c++/10/bits/stl_map.h:215:7: note: candidate: ‘std::map<_Key, _Tp, _Compare, _Alloc>::map(std::map<_Key, _Tp, _Compare, _Alloc>&&) [with _Key = std::__cxx11::basic_string<char>; _Tp = std::variant<std::function<bool(bool)>, std::function<int(int)> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >]’
215 | map(map&&) = default;
| ^~~
/usr/include/c++/10/bits/stl_map.h:215:7: note: candidate expects 1 argument, 2 provided
/usr/include/c++/10/bits/stl_map.h:207:7: note: candidate: ‘std::map<_Key, _Tp, _Compare, _Alloc>::map(const std::map<_Key, _Tp, _Compare, _Alloc>&) [with _Key = std::__cxx11::basic_string<char>; _Tp = std::variant<std::function<bool(bool)>, std::function<int(int)> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >]’
207 | map(const map&) = default;
| ^~~
/usr/include/c++/10/bits/stl_map.h:207:7: note: candidate expects 1 argument, 2 provided
/usr/include/c++/10/bits/stl_map.h:194:7: note: candidate: ‘std::map<_Key, _Tp, _Compare, _Alloc>::map(const _Compare&, const allocator_type&) [with _Key = std::__cxx11::basic_string<char>; _Tp = std::variant<std::function<bool(bool)>, std::function<int(int)> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >; std::map<_Key, _Tp, _Compare, _Alloc>::allocator_type = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >]’
194 | map(const _Compare& __comp,
| ^~~
/usr/include/c++/10/bits/stl_map.h:194:27: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘const std::less<std::__cxx11::basic_string<char> >&’
194 | map(const _Compare& __comp,
| ~~~~~~~~~~~~~~~~^~~~~~
/usr/include/c++/10/bits/stl_map.h:185:7: note: candidate: ‘std::map<_Key, _Tp, _Compare, _Alloc>::map() [with _Key = std::__cxx11::basic_string<char>; _Tp = std::variant<std::function<bool(bool)>, std::function<int(int)> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::variant<std::function<bool(bool)>, std::function<int(int)> > > >]’
185 | map() = default;
| ^~~
/usr/include/c++/10/bits/stl_map.h:185:7: note: candidate expects 0 arguments, 2 provided
This has nothing to do with the one-user-defined-conversion rule. It's easy to see this by taking your example and replacing FunctionType<int> with FunctionType<std::string> - everything compiles.
variant<X, Y> is implicitly convertible from everything that converts to X or Y, provided that it can unambiguously determine the type to convert to. The proviso is important because std::function doesn't require exact matches: a std::function<bool(bool)> accepts everything that can be called with a bool and returns something that can be converted to a bool. Obviously [](bool x) { return x; } meets this requirement, but [](int x) { return x; } does so too. Similarly, both of these lambdas can be converted to a std::function<int(int)> because they can both be called with an int to produce something that's convertible to an int.
Since the lambdas are convertible to both alternatives, and there is no ordering between the two, variant will just refuse to convert from it. This is why replacing FunctionType<int> with FunctionType<std::string> makes it compile - only the bool alternative is viable in that case.
There's some code I've written which I have trouble with, but I've tried to write a simplified version of it to possibly reproduce the error I'm encountering:
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
struct test{
float y;
};
typedef pair<int, int> intpair;
map<intpair, test> mp;
void func(test &obj){
obj.y = 23.5;
}
int main () {
test* obj = new test;
auto key = make_pair(1,1);
mp.insert(key, obj);
func(*obj);
//cout << *(obj->y);
delete obj;
return 0;
}
What I would like to do is map a pair to a custom struct test that I have created. I get the following error:
main.cpp: In function ‘int main()’:
main.cpp:22:22: error: no matching function for call to ‘std::map, test>::insert(std::pair&, test*&)’
mp.insert(key, obj);
^
In file included from /usr/include/c++/6/map:61:0,
from /usr/include/x86_64-linux-gnu/c++/6/bits/stdc++.h:81,
from main.cpp:2:
/usr/include/c++/6/bits/stl_map.h:731:7: note: candidate: std::pair, std::_Select1st >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const value_type&) [with _Key = std::pair; _Tp = test; _Compare = std::less >; _Alloc = std::allocator, test> >; typename std::_Rb_tree<_Key, std::pair, std::_Select1st >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind >::other>::iterator = std::_Rb_tree_iterator, test> >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair, test>]
insert(const value_type& __x)
^~~~~~
/usr/include/c++/6/bits/stl_map.h:731:7: note: candidate expects 1 argument, 2 provided
/usr/include/c++/6/bits/stl_map.h:739:9: note: candidate: template std::pair, std::_Select1st >, _Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(_Pair&&) [with _Pair = _Pair; = ; _Key = std::pair; _Tp = test; _Compare = std::less >; _Alloc = std::allocator, test> >]
insert(_Pair&& __x)
^~~~~~
/usr/include/c++/6/bits/stl_map.h:739:9: note: template argument deduction/substitution failed:
main.cpp:22:22: note: candidate expects 1 argument, 2 provided
mp.insert(key, obj);
^
In file included from /usr/include/c++/6/map:61:0,
from /usr/include/x86_64-linux-gnu/c++/6/bits/stdc++.h:81,
from main.cpp:2:
/usr/include/c++/6/bits/stl_map.h:752:7: note: candidate: void std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::initializer_list >) [with _Key = std::pair; _Tp = test; _Compare = std::less >; _Alloc = std::allocator, test> >]
insert(std::initializer_list<value_type> __list)
^~~~~~
/usr/include/c++/6/bits/stl_map.h:752:7: note: candidate expects 1 argument, 2 provided
/usr/include/c++/6/bits/stl_map.h:781:7: note: candidate: 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::pair; _Tp = test; _Compare = std::less >; _Alloc = std::allocator, test> >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator, test> >; std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator, test> >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair, test>]
insert(const_iterator __position, const value_type& __x)
^~~~~~
/usr/include/c++/6/bits/stl_map.h:781:7: note: no known conversion for argument 1 from ‘std::pair’ to ‘std::map, test>::const_iterator {aka std::_Rb_tree_const_iterator, test> >}’
/usr/include/c++/6/bits/stl_map.h:792:9: note: candidate: template 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; = ; _Key = std::pair; _Tp = test; _Compare = std::less >; _Alloc = std::allocator, test> >]
insert(const_iterator __position, _Pair&& __x)
^~~~~~
/usr/include/c++/6/bits/stl_map.h:792:9: note: template argument deduction/substitution failed:
main.cpp:22:22: note: cannot convert ‘key’ (type ‘std::pair’) to type ‘std::map, test>::const_iterator {aka std::_Rb_tree_const_iterator, test> >}’
mp.insert(key, obj);
^
In file included from /usr/include/c++/6/map:61:0,
from /usr/include/x86_64-linux-gnu/c++/6/bits/stdc++.h:81,
from main.cpp:2:
/usr/include/c++/6/bits/stl_map.h:807:9: note: candidate: template void std::map<_Key, _Tp, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _InputIterator = _InputIterator; _Key = std::pair; _Tp = test; _Compare = std::less >; _Alloc = std::allocator, test> >]
insert(_InputIterator __first, _InputIterator __last)
^~~~~~
/usr/include/c++/6/bits/stl_map.h:807:9: note: template argument deduction/substitution failed:
main.cpp:22:22: note: deduced conflicting types for parameter ‘_InputIterator’ (‘std::pair’ and ‘test*’)
mp.insert(key, obj);
Also, I'm sure that I'm going wrong in the way I access my obj's member y (cout statement commented out); How do I go about resolving these issues?
There are no overload of std::map::insert that takes a key and a value.
You can use operator[] to add a new element:
mp[key] = *obj;
Or std::map::insert_or_assign since C++17:
mp.insert_or_assign(key, *obj);
Another point is that type of obj is test* while the type of values of the map mp has type test. The pointer should be dereferenced (like my examples above) or the type of values should be changed to pointers to do this insertion.
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
This question already has answers here:
C++: Is it possible to use a reference as the value in a map?
(6 answers)
Closed 5 years ago.
I'm having trouble inserting a reference to an object into a map in C++.
Here is some sample code to show what I want to do:
#include <iostream>
#include <map>
class Foo {
public:
// ...
void addToMap();
};
std::map<std::string, Foo&> myMap;
void Foo::addToMap() {
myMap.insert(std::make_pair(std::string("hello"), *this));
}
int main() {
Foo foo;
foo.addToMap();
}
When I compile, I get a very cryptic error message of
main.cpp: In member function ‘void Foo::addToMap()’:
main.cpp:12:48: error: no matching function for call to ‘std::map<std::__cxx11::basic_string<char>, Foo&>::insert(std::pair<const char*, Foo>)’
myMap.insert(std::make_pair("hello", *this));
^
In file included from /usr/include/c++/6.3.1/map:61:0,
from main.cpp:2:
/usr/include/c++/6.3.1/bits/stl_map.h:731:7: note: candidate: 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::__cxx11::basic_string<char>; _Tp = Foo&; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, Foo&> >; 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::__cxx11::basic_string<char>, Foo&> >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const std::__cxx11::basic_string<char>, Foo&>]
insert(const value_type& __x)
^~~~~~
/usr/include/c++/6.3.1/bits/stl_map.h:731:7: note: no known conversion for argument 1 from ‘std::pair<const char*, Foo>’ to ‘const value_type& {aka const std::pair<const std::__cxx11::basic_string<char>, Foo&>&}’
/usr/include/c++/6.3.1/bits/stl_map.h:739:9: note: candidate: 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::__cxx11::basic_string<char>; _Tp = Foo&; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, Foo&> >]
insert(_Pair&& __x)
^~~~~~
/usr/include/c++/6.3.1/bits/stl_map.h:739:9: note: template argument deduction/substitution failed:
/usr/include/c++/6.3.1/bits/stl_map.h:735:32: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
template<typename _Pair, typename = typename
^~~~~~~~
/usr/include/c++/6.3.1/bits/stl_map.h:752:7: note: candidate: void std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::initializer_list<std::pair<const _Key, _Tp> >) [with _Key = std::__cxx11::basic_string<char>; _Tp = Foo&; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, Foo&> >]
insert(std::initializer_list<value_type> __list)
^~~~~~
/usr/include/c++/6.3.1/bits/stl_map.h:752:7: note: no known conversion for argument 1 from ‘std::pair<const char*, Foo>’ to ‘std::initializer_list<std::pair<const std::__cxx11::basic_string<char>, Foo&> >’
/usr/include/c++/6.3.1/bits/stl_map.h:781:7: note: candidate: 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::__cxx11::basic_string<char>; _Tp = Foo&; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, Foo&> >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::__cxx11::basic_string<char>, Foo&> >; std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const std::__cxx11::basic_string<char>, Foo&> >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const std::__cxx11::basic_string<char>, Foo&>]
insert(const_iterator __position, const value_type& __x)
^~~~~~
/usr/include/c++/6.3.1/bits/stl_map.h:781:7: note: candidate expects 2 arguments, 1 provided
/usr/include/c++/6.3.1/bits/stl_map.h:792:9: note: candidate: 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::__cxx11::basic_string<char>; _Tp = Foo&; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, Foo&> >]
insert(const_iterator __position, _Pair&& __x)
^~~~~~
/usr/include/c++/6.3.1/bits/stl_map.h:792:9: note: template argument deduction/substitution failed:
main.cpp:12:48: note: candidate expects 2 arguments, 1 provided
myMap.insert(std::make_pair("hello", *this));
^
In file included from /usr/include/c++/6.3.1/map:61:0,
from main.cpp:2:
/usr/include/c++/6.3.1/bits/stl_map.h:807:9: note: candidate: template<class _InputIterator> void std::map<_Key, _Tp, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _InputIterator = _InputIterator; _Key = std::__cxx11::basic_string<char>; _Tp = Foo&; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, Foo&> >]
insert(_InputIterator __first, _InputIterator __last)
^~~~~~
/usr/include/c++/6.3.1/bits/stl_map.h:807:9: note: template argument deduction/substitution failed:
main.cpp:12:48: note: candidate expects 2 arguments, 1 provided
myMap.insert(std::make_pair("hello", *this));
I have no idea how to make the pointer this into a reference, which I can then insert into the map. How would I go about fixing the code?
The standard library containers can't contain references. Use pointers instead, or wrap your references to T in std::reference_wrapper<T> instead, e.g.
#include <functional>
#include <map>
#include <string>
std::map<std::string, std::reference_wrapper<Foo> > myMap;
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).