2
votes

When creating my own allocator in c++11 I am implementing the following interfaces. This works with vector but when trying to use this with map I get errors on missing items. I thought this was all I need to implement for c++11 since it will use allocator_traits in the stl implementations. What am I missing here? Do I need to define more methods / data structures for an allocator for std::map? I am seeing the following errors when trying to compile currently (see below). Line 3 main.cpp is just

#include <map>

template <class T> struct MyAllocator {
    typedef T value_type;
    MyAllocator() noexcept;  // only required if used
    MyAllocator(const MyAllocator&) noexcept;  // copies must be equal
    MyAllocator(MyAllocator&&) noexcept;  // not needed if copy ctor is good enough
    template <class U> MyAllocator(const MyAllocator<U>& u) noexcept; 
        // requires: *this == MyAllocator(u)
    value_type* allocate(std::size_t);
    void deallocate(value_type*, std::size_t) noexcept;
};

template <class T, class U> bool
operator==(const MyAllocator<T>&, const MyAllocator<U>&) noexcept;

Errors:

In file included from /opt/gcc-4.8.1/usr/local/include/c++/4.8.1/map:61:0,
from main.cpp:3:
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_map.h: In instantiation of ‘class std::map, MyAlloc >’:
main.cpp:146:14: required from here
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_map.h:143:58: error: no type named ‘pointer’ in ‘std::map, MyAlloc >::_Pair_alloc_type {aka class MyAlloc, 200 typedef typename _Pair_alloc_type::pointer pointer; ^
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_map.h:144:58: error: no type named ‘const_pointer’ in ‘std::map, MyAlloc >::_Pair_alloc_type {aka class MyAlloc /opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_map.h:145:58: error: no type named ‘reference’ in ‘std::map, MyAlloc >::_Pair_alloc_type {aka class MyAlloc, 2 typedef typename _Pair_alloc_type::reference reference; ^
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_map.h:146:58: error: no type named ‘const_reference’ in ‘std::map, MyAlloc >::_Pair_alloc_type {aka class MyAlloc In file included from /opt/gcc-4.8.1/usr/local/include/c++/4.8.1/map:60:0,
from main.cpp:3:
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_tree.h: In instantiation of ‘void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_destroy_node(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_t /opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_tree.h:1124:23:
required from ‘void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_erase(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type /opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_tree.h:671:28:
required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::~_Rb_tree() [with _Key = int; _Val = std::pair; _KeyOfValue = std::
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_map.h:96:11:
required from here
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_tree.h:421:2: error: ‘std::_Rb_tree, std::_Select1st >, std::less, MyAlloc, 200ul> >:
_M_get_Node_allocator().destroy(__p); ^
make: *** [main.o] Error 1

2
note this works after adding construct, destroy and some type defs for pointer etc. It's just that in all the literature I didn't think I needed these. - bjackfly
some of your lines are unduly long - sp2danny
Could you please post a MCVE? This will make it ease for people to help you. Ideone is a useful tool to showcase the compilation errors with less clutter. - Fabio A. Correa
It is likely that gcc-4.8.1 simply does not yet implement the full C++11 spec in this area. - Howard Hinnant
thanks @HowardHinnant upvoted - bjackfly

2 Answers

1
votes

The first errors are solved using some typedefs within MyAllocator:

typedef T& reference;
typedef const T& const_reference;
typedef T* pointer;
typedef const T* const_pointer;

Please post your new compilation output.

1
votes

Basically as my comment suggested I needed to put the typedefs for the following and a construct and destroy

        template <class U> 
        struct rebind {typedef MyAlloc<U, N> other;};  

        typedef size_t size_type;                                                                                                                                                                                                      
        typedef ptrdiff_t difference_type;
        typedef T* pointer;
        typedef const T* const_pointer;
        typedef T& reference;                                                                                                                                                                                                          
        typedef const T& const_reference;                                                                                                                                                                                              
        typedef T value_type;          

       /// Call constructor with many arguments                                                                                                                                                                                       
        template<typename U, typename... Args>                                                                                                                                                                                         
        void construct(U* p, Args&&... args)                                                                                                                                                                                           
        {                                                                                                                                                                                                                              
            // Placement new                                                                                                                                                                                                           
            ::new((void *)p) U(std::forward<Args>(args)...);                                                                                                                                                                           
        }                                                                                                                                                                                                                              
        /// Call destructor                                                                                                                                                                                                            
        template<typename U>                                                                                                                                                                                                           
        void destroy(U* p)                                                                                                                                                                                                             
        {                                                                                                                                                                                                                              
            p->~U();                                                                                                                                                                                                                   
        }