Custom allocator fails for std::map - c++

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

I haven't tried fixing it but it seems you haven't defined a constructor which takes an allocator instantiation with a different template argument. That is, you are missing something like
template <typename T>
template <typename O>
mmap_allocator<T>::mmap_allocator(mmap_allocator<O> const& other) {
...
}
From the looks of it, the error stems from trying to construct an allocator type obtained from rebind with some other allocator.

Related

C++ Map with key and value data type as uint32_t gives error

On using uint32_t data type for the key and value in a map. I am getting an error no known conversion for argument.
Here is what I tried
int main() {
uint32_t a = 5;
uint32_t b = 9;
map <uint32_t, uint32_t> Mapper;
Mapper.insert({9,8});
auto imageFoundIt = Mapper.find(make_pair(a, b));
return 0;
}
Here is the error stack trace
g++ /tmp/cpzeeEDm4C.cpp
/tmp/cpzeeEDm4C.cpp: In function 'int main()':
/tmp/cpzeeEDm4C.cpp:10:52: error: no matching function for call to 'std::map<unsigned int, unsigned int>::find(std::pair<unsigned int, unsigned int>)'
10 | auto imageFoundIt = Mapper.find(make_pair(a, b));
| ^
In file included from /usr/include/c++/9/map:61,
from /usr/include/x86_64-linux-gnu/c++/9/bits/stdc++.h:81,
from /tmp/cpzeeEDm4C.cpp:3:
/usr/include/c++/9/bits/stl_map.h:1168:7: note: candidate: 'std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::find(const key_type&) [with _Key = unsigned int; _Tp = unsigned int; _Compare = std::less<unsigned int>; _Alloc = std::allocator<std::pair<const unsigned int, unsigned int> >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const unsigned int, unsigned int> >; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = unsigned int]'
1168 | find(const key_type& __x)
| ^~~~
/usr/include/c++/9/bits/stl_map.h:1168:28: note: no known conversion for argument 1 from 'std::pair<unsigned int, unsigned int>' to 'const key_type&' {aka 'const unsigned int&'}
1168 | find(const key_type& __x)
| ~~~~~~~~~~~~~~~~^~~
/usr/include/c++/9/bits/stl_map.h:1174:2: note: candidate: 'template<class _Kt> decltype (((std::map<_Key, _Tp, _Compare, _Alloc>*)this)->std::map<_Key, _Tp, _Compare, _Alloc>::_M_t._M_find_tr(__x)) std::map<_Key, _Tp, _Compare, _Alloc>::find(const _Kt&) [with _Kt = _Kt; _Key = unsigned int; _Tp = unsigned int; _Compare = std::less<unsigned int>; _Alloc = std::allocator<std::pair<const unsigned int, unsigned int> >]'
1174 | find(const _Kt& __x) -> decltype(_M_t._M_find_tr(__x))
| ^~~~
/usr/include/c++/9/bits/stl_map.h:1174:2: note: template argument deduction/substitution failed:
/usr/include/c++/9/bits/stl_map.h: In substitution of 'template<class _Kt> decltype (((std::map<unsigned int, unsigned int>*)this)->std::map<unsigned int, unsigned int>::_M_t.std::_Rb_tree<unsigned int, std::pair<const unsigned int, unsigned int>, std::_Select1st<std::pair<const unsigned int, unsigned int> >, std::less<unsigned int>, std::allocator<std::pair<const unsigned int, unsigned int> > >::_M_find_tr(__x)) std::map<unsigned int, unsigned int>::find<_Kt>(const _Kt&) [with _Kt = std::pair<unsigned int, unsigned int>]':
/tmp/cpzeeEDm4C.cpp:10:52: required from here
/usr/include/c++/9/bits/stl_map.h:1174:2: error: no matching function for call to 'std::_Rb_tree<unsigned int, std::pair<const unsigned int, unsigned int>, std::_Select1st<std::pair<const unsigned int, unsigned int> >, std::less<unsigned int>, std::allocator<std::pair<const unsigned int, unsigned int> > >::_M_find_tr(const std::pair<unsigned int, unsigned int>&)'
In file included from /usr/include/c++/9/map:60,
from /usr/include/x86_64-linux-gnu/c++/9/bits/stdc++.h:81,
from /tmp/cpzeeEDm4C.cpp:3:
/usr/include/c++/9/bits/stl_tree.h:1306:2: note: candidate: 'template<class _Kt, class _Req> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_find_tr(const _Kt&) [with _Kt = _Kt; _Req = _Req; _Key = unsigned int; _Val = std::pair<const unsigned int, unsigned int>; _KeyOfValue = std::_Select1st<std::pair<const unsigned int, unsigned int> >; _Compare = std::less<unsigned int>; _Alloc = std::allocator<std::pair<const unsigned int, unsigned int> >]'
1306 | _M_find_tr(const _Kt& __k)
| ^~~~~~~~~~
/usr/include/c++/9/bits/stl_tree.h:1306:2: note: template argument deduction/substitution failed:
/usr/include/c++/9/bits/stl_tree.h: In substitution of 'template<class _Cmp, class _SfinaeType> using __has_is_transparent_t = typename std::__has_is_transparent<_Cmp, _SfinaeType>::type [with _Cmp = std::less<unsigned int>; _SfinaeType = std::pair<unsigned int, unsigned int>]':
/usr/include/c++/9/bits/stl_tree.h:1304:9: required by substitution of 'template<class _Kt> decltype (((std::map<unsigned int, unsigned int>*)this)->std::map<unsigned int, unsigned int>::_M_t.std::_Rb_tree<unsigned int, std::pair<const unsigned int, unsigned int>, std::_Select1st<std::pair<const unsigned int, unsigned int> >, std::less<unsigned int>, std::allocator<std::pair<const unsigned int, unsigned int> > >::_M_find_tr(__x)) std::map<unsigned int, unsigned int>::find<_Kt>(const _Kt&) [with _Kt = std::pair<unsigned int, unsigned int>]'
/tmp/cpzeeEDm4C.cpp:10:52: required from here
/usr/include/c++/9/bits/stl_tree.h:425:11: error: no type named 'type' in 'struct std::__has_is_transparent<std::less<unsigned int>, std::pair<unsigned int, unsigned int>, void>'
425 | using __has_is_transparent_t
| ^~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/9/bits/stl_map.h: In substitution of 'template<class _Kt> decltype (((std::map<unsigned int, unsigned int>*)this)->std::map<unsigned int, unsigned int>::_M_t.std::_Rb_tree<unsigned int, std::pair<const unsigned int, unsigned int>, std::_Select1st<std::pair<const unsigned int, unsigned int> >, std::less<unsigned int>, std::allocator<std::pair<const unsigned int, unsigned int> > >::_M_find_tr(__x)) std::map<unsigned int, unsigned int>::find<_Kt>(const _Kt&) [with _Kt = std::pair<unsigned int, unsigned int>]':
/tmp/cpzeeEDm4C.cpp:10:52: required from here
/usr/include/c++/9/bits/stl_tree.h:1315:2: note: candidate: 'template<class _Kt, class _Req> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_find_tr(const _Kt&) const [with _Kt = _Kt; _Req = _Req; _Key = unsigned int; _Val = std::pair<const unsigned int, unsigned int>; _KeyOfValue = std::_Select1st<std::pair<const unsigned int, unsigned int> >; _Compare = std::less<unsigned int>; _Alloc = std::allocator<std::pair<const unsigned int, unsigned int> >]'
1315 | _M_find_tr(const _Kt& __k) const
| ^~~~~~~~~~
/usr/include/c++/9/bits/stl_tree.h:1315:2: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/9/map:61,
from /usr/include/x86_64-linux-gnu/c++/9/bits/stdc++.h:81,
from /tmp/cpzeeEDm4C.cpp:3:
/usr/include/c++/9/bits/stl_map.h:1193:7: note: candidate: 'std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator std::map<_Key, _Tp, _Compare, _Alloc>::find(const key_type&) const [with _Key = unsigned int; _Tp = unsigned int; _Compare = std::less<unsigned int>; _Alloc = std::allocator<std::pair<const unsigned int, unsigned int> >; std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const unsigned int, unsigned int> >; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = unsigned int]'
1193 | find(const key_type& __x) const
| ^~~~
/usr/include/c++/9/bits/stl_map.h:1193:28: note: no known conversion for argument 1 from 'std::pair<unsigned int, unsigned int>' to 'const key_type&' {aka 'const unsigned int&'}
1193 | find(const key_type& __x) const
| ~~~~~~~~~~~~~~~~^~~
/usr/include/c++/9/bits/stl_map.h:1199:2: note: candidate: 'template<class _Kt> decltype (((const std::map<_Key, _Tp, _Compare, _Alloc>*)this)->std::map<_Key, _Tp, _Compare, _Alloc>::_M_t._M_find_tr(__x)) std::map<_Key, _Tp, _Compare, _Alloc>::find(const _Kt&) const [with _Kt = _Kt; _Key = unsigned int; _Tp = unsigned int; _Compare = std::less<unsigned int>; _Alloc = std::allocator<std::pair<const unsigned int, unsigned int> >]'
1199 | find(const _Kt& __x) const -> decltype(_M_t._M_find_tr(__x))
| ^~~~
/usr/include/c++/9/bits/stl_map.h:1199:2: note: template argument deduction/substitution failed:
/usr/include/c++/9/bits/stl_map.h: In substitution of 'template<class _Kt> decltype (((const std::map<unsigned int, unsigned int>*)this)->std::map<unsigned int, unsigned int>::_M_t.std::_Rb_tree<unsigned int, std::pair<const unsigned int, unsigned int>, std::_Select1st<std::pair<const unsigned int, unsigned int> >, std::less<unsigned int>, std::allocator<std::pair<const unsigned int, unsigned int> > >::_M_find_tr(__x)) std::map<unsigned int, unsigned int>::find<_Kt>(const _Kt&) const [with _Kt = std::pair<unsigned int, unsigned int>]':
/tmp/cpzeeEDm4C.cpp:10:52: required from here
/usr/include/c++/9/bits/stl_map.h:1199:2: error: no matching function for call to 'std::_Rb_tree<unsigned int, std::pair<const unsigned int, unsigned int>, std::_Select1st<std::pair<const unsigned int, unsigned int> >, std::less<unsigned int>, std::allocator<std::pair<const unsigned int, unsigned int> > >::_M_find_tr(const std::pair<unsigned int, unsigned int>&) const'
In file included from /usr/include/c++/9/map:60,
from /usr/include/x86_64-linux-gnu/c++/9/bits/stdc++.h:81,
from /tmp/cpzeeEDm4C.cpp:3:
/usr/include/c++/9/bits/stl_tree.h:1306:2: note: candidate: 'template<class _Kt, class _Req> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_find_tr(const _Kt&) [with _Kt = _Kt; _Req = _Req; _Key = unsigned int; _Val = std::pair<const unsigned int, unsigned int>; _KeyOfValue = std::_Select1st<std::pair<const unsigned int, unsigned int> >; _Compare = std::less<unsigned int>; _Alloc = std::allocator<std::pair<const unsigned int, unsigned int> >]'
1306 | _M_find_tr(const _Kt& __k)
| ^~~~~~~~~~
/usr/include/c++/9/bits/stl_tree.h:1306:2: note: template argument deduction/substitution failed:
/usr/include/c++/9/bits/stl_tree.h:1315:2: note: candidate: 'template<class _Kt, class _Req> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_find_tr(const _Kt&) const [with _Kt = _Kt; _Req = _Req; _Key = unsigned int; _Val = std::pair<const unsigned int, unsigned int>; _KeyOfValue = std::_Select1st<std::pair<const unsigned int, unsigned int> >; _Compare = std::less<unsigned int>; _Alloc = std::allocator<std::pair<const unsigned int, unsigned int> >]'
1315 | _M_find_tr(const _Kt& __k) const
| ^~~~~~~~~~
/usr/include/c++/9/bits/stl_tree.h:1315:2: note: template argument deduction/substitution failed:
How can I use uint32_t as key and value here?
The problem is that std::map::find takes the key(which is of type Key) value of the element to search for as argument but you're providing a std::pair and hence the error.
So solve this just replace the call to find with:
//------------------------------v--->pass the key value
auto imageFoundIt = Mapper.find(a)
which will give return an iterator to an element with key equivalent to key. And if no such element is found, past-the-end iterator will be returned.

How to print my map<pair<int,int>, pair<int,int>> in cout

#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
int main() {
map<pair<int,int>,pair<int,int>> items;
items.insert(make_pair(1,20),make_pair(0,0));
items.insert(make_pair(2,10),make_pair(0,0));
items.insert(make_pair(3,30),make_pair(0,0));
items.insert(make_pair(4,5),make_pair(0,0));
items.insert(make_pair(5,35),make_pair(0,0));
map<pair<int,int>,pair<int,int>>::iterator it;
cout<<"Class ID:\t\t\tSamples:\t\t\tTP:\t\t\tPrecision:"<<endl;
for(it = items.begin();it!=items.end();++it)
{
cout<<(it->first).first<<"\t\t\t"<<(it->first).second<<"\t\t\t"<<(it->second).first<<"\t\t\t"<<(it->second).second<<endl;
}
}
I have a code like this but i can't print my values. Can someone help me please?
I'm getting interesting compiler error :
Here is the text of the error :
In file included from C:/PROGRA~1/MINGW-~1/X86_64~1.0-P/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/map:60,
from C:\Users\Fatih\Desktop\clion\quiz3\main.cpp:2:
C:/PROGRA~1/MINGW-~1/X86_64~1.0-P/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_tree.h: In instantiation of 'void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(_II, _II) [with _InputIterator = std::pair<int, int>; _Key = std::pair<int, int>; _Val = std::pair<const std::pair<int, int>, std::pair<int, int> >; _KeyOfValue = std::_Select1st<std::pair<const std::pair<int, int>, std::pair<int, int> > >; _Compare = std::less<std::pair<int, int> >; _Alloc = std::allocator<std::pair<const std::pair<int, int>, std::pair<int, int> > >]':
C:/PROGRA~1/MINGW-~1/X86_64~1.0-P/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_map.h:893:4: required from 'void std::map<_Key, _Tp, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _InputIterator = std::pair<int, int>; _Key = std::pair<int, int>; _Tp = std::pair<int, int>; _Compare = std::less<std::pair<int, int> >; _Alloc = std::allocator<std::pair<const std::pair<int, int>, std::pair<int, int> > >]'
C:\Users\Fatih\Desktop\clion\quiz3\main.cpp:10:48: required from here
C:/PROGRA~1/MINGW-~1/X86_64~1.0-P/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_tree.h:2467:28: error: no match for 'operator++' (operand type is 'std::pair<int, int>')
for (; __first != __last; ++__first)
^~~~~~~~~
C:/PROGRA~1/MINGW-~1/X86_64~1.0-P/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_tree.h:2468:29: error: no match for 'operator*' (operand type is 'std::pair<int, int>')
_M_insert_unique_(end(), *__first, __an);
^~~~~~~~
std::map::insert takes a parameter of value_type which is std::pair<const Key, Value>. That means you need to combine make_pair(1,20),make_pair(0,0) into a single parameter so you can call the function. That would look like
items.insert({make_pair(1,20),make_pair(0,0)});
// ^curly braces create value_type^
items.insert({make_pair(2,10),make_pair(0,0)});
items.insert({make_pair(3,30),make_pair(0,0)});
items.insert({make_pair(4,5),make_pair(0,0)});
items.insert({make_pair(5,35),make_pair(0,0)});
Alternatively you can use emplace which will take parameters to construct a value_type. That lets you get away without using the curly braces and looks like
items.emplace(make_pair(1,20),make_pair(0,0));
items.emplace(make_pair(2,10),make_pair(0,0));
items.emplace(make_pair(3,30),make_pair(0,0));
items.emplace(make_pair(4,5),make_pair(0,0));
items.emplace(make_pair(5,35),make_pair(0,0));

What's wrong with this moveable type for std::map?

I want to put a moveable but not copyable type as a value in std::map. Here is some simple code to test the principle.
#include <map>
struct Foo
{
Foo ();
Foo (const Foo &) = delete;
Foo & operator = (const Foo &) = delete;
Foo (Foo &&) {}
Foo & operator = (Foo &&) {return *this;}
};
int main ()
{
std :: map <int, Foo> m;
m .insert (std :: make_pair (123, Foo ()));
}
I compile this with g++ test.cpp --std=c++0x (gcc version 4.5.1 on Ubuntu 12.04). There is a big ugly error as shown below. What is the problem?
In file included from /usr/local/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/bits/stl_algobase.h:66:0,
from /usr/local/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/bits/stl_tree.h:62,
from /usr/local/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/map:60,
from test.cpp:1: test.cpp: In copy constructor ‘std::pair<const int, Foo>::pair(const std::pair<const int, Foo>&)’: /usr/local/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/bits/stl_pair.h:72:5: instantiated from ‘std::_Rb_tree_node<_Val>::_Rb_tree_node(_Args&& ...) [with _Args = {const std::pair<const int, Foo>&}, _Val = std::pair<const int, Foo>]’ /usr/local/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/ext/new_allocator.h:111:4: instantiated from ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*,
_Args&& ...) [with _Args = {const std::pair<const int, Foo>&}, _Tp = std::_Rb_tree_node<std::pair<const int, Foo> >, _Tp* = std::_Rb_tree_node<std::pair<const int, Foo> >*]’ /usr/local/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/bits/stl_tree.h:394:8: instantiated from ‘std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val,
_KeyOfValue, _Compare, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {const std::pair<const int, Foo>&}, _Key = int, _Val = std::pair<const int, Foo>, _KeyOfValue = std::_Select1st<std::pair<const int, Foo> >, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, Foo> >, std::_Rb_tree_node<_Val>* = std::_Rb_tree_node<std::pair<const int, Foo> >*]’ /usr/local/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/bits/stl_tree.h:899:42: instantiated from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare,
_Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_(const std::_Rb_tree_node_base*, const std::_Rb_tree_node_base*, const _Val&) [with _Key = int, _Val = std::pair<const int, Foo>, _KeyOfValue = std::_Select1st<std::pair<const int, Foo> >, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, Foo> >, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const int, Foo> >, const std::_Rb_tree_node_base* = const std::_Rb_tree_node_base*]’ /usr/local/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/bits/stl_tree.h:1191:65: instantiated from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare,
_Alloc>::_M_insert_unique(const _Val&) [with _Key = int, _Val = std::pair<const int, Foo>, _KeyOfValue = std::_Select1st<std::pair<const int, Foo> >, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, Foo> >]’ /usr/local/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/bits/stl_map.h:501:41: instantiated from ‘std::pair<typename std::map<_Key, _Tp, _Compare,
_Alloc>::_Rep_type::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const std::map<_Key, _Tp, _Compare, _Alloc>::value_type&) [with _Key = int, _Tp = Foo, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, Foo> >, typename std::map<_Key, _Tp, _Compare, _Alloc>::_Rep_type::iterator = std::_Rb_tree_iterator<std::pair<const int, Foo> >, std::map<_Key,
_Tp, _Compare, _Alloc>::value_type = std::pair<const int, Foo>]’ test.cpp:20:43: instantiated from here test.cpp:7:2: error: deleted function ‘Foo::Foo(const Foo&)’ /usr/local/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/bits/stl_pair.h:72:5: error: used here In file included from /usr/local/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/map:60:0,
from test.cpp:1: /usr/local/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/bits/stl_tree.h: In constructor ‘std::_Rb_tree_node<_Val>::_Rb_tree_node(_Args&& ...) [with _Args = {const std::pair<const int, Foo>&}, _Val = std::pair<const int, Foo>]’: /usr/local/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/bits/stl_tree.h:136:49: note: synthesized method ‘std::pair<const int, Foo>::pair(const std::pair<const int, Foo>&)’ first required here
I'm adding some details for future references: this bug as Quux pointed out was caused in gcc 4.5.1 by a problem in the move constructor for std::pair.
As of today the issue has been fixed and you should either upgrade your compiler version or workaround by using another version of the standard library.
Your code works just fine

Is it possible to use STL copy function with map

I wonder if there is any trick to use copy with maps to copy the contents of map into an array. Because STL maps are by the combination of a key value and a mapped value an element of a map forms a key value pair. That prevents us to use standard algorithms like std::copy. For example following code gives error:
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
int
main()
{
std::map <int, double> test(4);
test[0] = 11;
test[2] = 1.23;
test[3] = 23.29;
test[1] = 12.12;
double *test_arr = (double *) malloc(4 * sizeof(double));
std::copy(test.begin(), test.end(), test_arr);
std::cout << test_arr[3] << std::endl;
return 0;
}
Error:
stl_copy_tests.cpp: In function ‘int main()’:
stl_copy_tests.cpp:9:32: error: no matching function for call to ‘std::map<int, double>::map(int)’
/usr/include/c++/4.5/bits/stl_map.h:170:7: note: candidates are: std::map<_Key, _Tp, _Compare, _Alloc>::map(const std::map<_Key, _Tp, _Compare, _Alloc>&) [with _Key = int, _Tp = double, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, double> >, std::map<_Key, _Tp, _Compare, _Alloc> = std::map<int, double>]
/usr/include/c++/4.5/bits/stl_map.h:159:7: note: std::map<_Key, _Tp, _Compare, _Alloc>::map(const _Compare&, const allocator_type&) [with _Key = int, _Tp = double, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, double> >, allocator_type = std::allocator<std::pair<const int, double> >]
/usr/include/c++/4.5/bits/stl_map.h:150:7: note: std::map<_Key, _Tp, _Compare, _Alloc>::map() [with _Key = int, _Tp = double, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, double> >]
In file included from /usr/include/c++/4.5/bits/char_traits.h:41:0,
from /usr/include/c++/4.5/ios:41,
from /usr/include/c++/4.5/ostream:40,
from /usr/include/c++/4.5/iostream:40,
from stl_copy_tests.cpp:1:
/usr/include/c++/4.5/bits/stl_algobase.h: In static member function ‘static _OI std::__copy_move<<anonymous>, <anonymous>, <template-parameter-1-3> >::__copy_m(_II, _II, _OI) [with _II = std::_Rb_tree_iterator<std::pair<const int, double> >, _OI = double*, bool <anonymous> = false, bool <anonymous> = false, <template-parameter-1-3> = std::bidirectional_iterator_tag]’:
/usr/include/c++/4.5/bits/stl_algobase.h:404:70: instantiated from ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false, _II = std::_Rb_tree_iterator<std::pair<const int, double> >, _OI = double*]’
/usr/include/c++/4.5/bits/stl_algobase.h:442:39: instantiated from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false, _II = std::_Rb_tree_iterator<std::pair<const int, double> >, _OI = double*]’
/usr/include/c++/4.5/bits/stl_algobase.h:474:18: instantiated from ‘_OI std::copy(_II, _II, _OI) [with _II = std::_Rb_tree_iterator<std::pair<const int, double> >, _OI = double*]’
stl_copy_tests.cpp:15:47: instantiated from here
/usr/include/c++/4.5/bits/stl_algobase.h:319:6: error: cannot convert ‘std::pair<const int, double>’ to ‘double’ in assignment
Is there any easy trick/hack to overcome this problem.
Disclaimer: Not interested in solutions that iterates over map in a for loop and adds elements to the array.
You could use std::transform instead:
template <typename T, typename U>
const U &extract_second(const std::pair<T,U> &p)
{
return p.second;
}
std::transform(test.begin(), test.end(), test_arr, extract_second<int,double>);
And as #Andre points out in a comment below, if you want a slightly more verbose overhead, you can avoid having to explicitly state the template arguments via a functor:
struct extract_second
{
template <typename T, typename U>
const U operator() (const std::pair<T,U> &p) const
{
return p.second;
}
};
std::transform(test.begin(), test.end(), test_arr, extract_second());
I'm sure there's a less-verbose solution using Boost binders, but I can't remember the syntax off the top of my head.
Ewww, malloc? Anyway, if you want to copy a map, you have to remember the keys too.
int main()
{
std::map <int, double> test(4);
test[0] = 11;
test[2] = 1.23;
test[3] = 23.29;
test[1] = 12.12;
std::vector<std::pair<int, double>> test_arr(test.size());
std::copy(test.begin(), test.end(), test_arr.begin());
std::cout << test_arr[3] << std::endl;
return 0;
}
If you consider std::map an STL container, then it is a container of
std::pair<key_type, mapped_type>. (This is what its value_type is
defined to be, and it is designed so that it can be used as a
container.) If you want simply one part of it, the correct function is
std::transform, with a transformation function which maps the
value_type to either the key_type or the mapped_type. (If you make
much use of std::pair—or std::map, whose value_type is an
std::pair, you should probably have functional objects for this in
your tool kit:
struct ExtractFirst
{
template<typename Pair>
typename boost::remove_const<typename Pair::first_type>::type
operator()( Pair const& from ) const
{
return from.first;
}
};
, and the same thing for ExtractSecond.
Your target would be an arraystd::vector[please!] of std::pair<int,double> objects unless, yes, you unroll it yourself.
(You could create your own InputIterator as a proxy, or play with std::transform and a std::back_inserter, but that's just being silly. You'll make your code far more verbose than just looping through the map.)
The simplest way is to use std::transform in combination with boost::bind:
typedef std::map<int, double> map_t;
map_t mm;
// add elements to mm
// ...
// copy
typedef std::vector<double> vec_t;
vec_t vv;
vv.reserve( mm.size() );
std::transform( mm.begin(), mm.end(), std::back_inserter(vv),
boost::bind( &map_t::value_type::second, _1 ) );
If you could use C++0x (without boost):
std::transform( mm.begin(), mm.end(), back_inserter(vv),
[](map_t::value_type val) -> double { return val.second; } );
// or
std::for_each( mm.begin(), mm.end(),
[&vv](map_t::value_type val) { vv.push_back( val.second ); } );

Why does this insertion into map<int, int> fails?

I'm writing a parser using Bison, and am using a map for semantic evaluation.
In one of the functions I have the following code:
map<int, int>* result = new map<int, int>();
map<int, int>::iterator liter;
map<int, int>::iterator riter;
liter = lval.polyMap.begin();
riter = rval.polyMap.begin();
l = liter->first;
r = riter->first;
(*result).insert(l, (booleanCondition()) ? liter->second : -liter->second);
(polyMap is of type map<int, int>).
And this gives me the following errors:
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_tree.h: In member functio
n `void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::insert_unique(
_II, _II) [with _InputIterator = int, _Key = int, _Val = std::pair<const int, in
t>, _KeyOfValue = std::_Select1st<std::pair<const int, int> >, _Compare = std::l
ess<int>, _Alloc = std::allocator<std::pair<const int, int> >]':
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_map.h:397: instantiated
from `void std::map<_Key, _Tp, _Compare, _Alloc>::insert(_InputIterator, _Input
Iterator) [with _InputIterator = int, _Key = int, _Tp = int, _Compare = std::les
s<int>, _Alloc = std::allocator<std::pair<const int, int> >]'
polynom.ypp:147: instantiated from here
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_tree.h:996: error: invali
d type argument of `unary *'
Where polynom.ypp line 147 contains (*result).insert(l, (booleanCondition()) ? liter->second : -liter->second);
What's the problem?
You might want to call (*result).insert(make_pair(l, (booleanCondition()) ? liter->second : -liter->second));