skip to Main Content

Here’s the code i’m able to compile with gcc:

#include <iostream>
#include <map>

template <class T>
class map_alloc {
public:
    typedef std::size_t      size_type;
    typedef std::ptrdiff_t   difference_type;
    typedef T*               pointer;
    typedef const T*         const_pointer;
    typedef T&               reference;
    typedef const T&         const_reference;
    typedef T                value_type;

    template <class U>
    struct rebind {
        typedef map_alloc<U> other;
    };

    pointer allocate(size_type n, const void* hint = 0) {
        T* t = (T*) malloc ( n * sizeof(T) );
        return t;
    }

    void deallocate(pointer p, size_type n) {
        free ( p );
    }

};

typedef map_alloc<std::map<int, int>::value_type> alloctor;

int main() {
    std::map<int, int, std::less<int>, alloctor> dummy;
    (void)(dummy);
    return 0;
}

But attempt to compile with MSVC failed with quite weired error (attached below).

Tested with:

g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
msvc 2022 community, toolset v143.

Any ideas? Any example of custom memory allocator for std::map on MSVC?

Thank you.

Build started at 1:02...
1>------ Build started: Project: malloc_tester, Configuration: Debug x64 ------
1>alloc_tester.cpp
1>C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27): error C2440: 'static_cast': cannot convert from 'map_alloc<U>' to 'map_alloc<U>'
1>C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27): error C2440:         with
1>C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27): error C2440:         [
1>C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27): error C2440:             U=std::_Tree_node<std::pair<const int,int>,std::_Default_allocator_traits<std::allocator<std::pair<const int,int>>>::void_pointer>
1>C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27): error C2440:         ]
1>C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27): error C2440:         and
1>C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27): error C2440:         [
1>C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27): error C2440:             U=std::_Container_proxy
1>C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27): error C2440:         ]
1>(compiling source file 'alloc_tester.cpp')
1>C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27):
1>'map_alloc<U>::map_alloc': no overloaded function could convert all the argument types
1>        with
1>        [
1>            U=std::_Container_proxy
1>        ]
1>  C:TempConsoleApplication4malloc_testeralloc_tester.cpp(29,1):
1>  could be 'map_alloc<U>::map_alloc(map_alloc<U> &&)'
1>        with
1>        [
1>            U=std::_Container_proxy
1>        ]
1>      C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27):
1>      'map_alloc<U>::map_alloc(map_alloc<U> &&)': cannot convert argument 1 from 'map_alloc<U>' to 'map_alloc<U> &&'
1>        with
1>        [
1>            U=std::_Container_proxy
1>        ]
1>        and
1>        [
1>            U=std::_Tree_node<std::pair<const int,int>,std::_Default_allocator_traits<std::allocator<std::pair<const int,int>>>::void_pointer>
1>        ]
1>        and
1>        [
1>            U=std::_Container_proxy
1>        ]
1>          C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27):
1>          Reason: cannot convert from 'map_alloc<U>' to 'map_alloc<U>'
1>        with
1>        [
1>            U=std::_Tree_node<std::pair<const int,int>,std::_Default_allocator_traits<std::allocator<std::pair<const int,int>>>::void_pointer>
1>        ]
1>        and
1>        [
1>            U=std::_Container_proxy
1>        ]
1>          C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27):
1>          No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>  C:TempConsoleApplication4malloc_testeralloc_tester.cpp(29,1):
1>  or       'map_alloc<U>::map_alloc(const map_alloc<U> &)'
1>        with
1>        [
1>            U=std::_Container_proxy
1>        ]
1>      C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27):
1>      'map_alloc<U>::map_alloc(const map_alloc<U> &)': cannot convert argument 1 from 'map_alloc<U>' to 'const map_alloc<U> &'
1>        with
1>        [
1>            U=std::_Container_proxy
1>        ]
1>        and
1>        [
1>            U=std::_Tree_node<std::pair<const int,int>,std::_Default_allocator_traits<std::allocator<std::pair<const int,int>>>::void_pointer>
1>        ]
1>        and
1>        [
1>            U=std::_Container_proxy
1>        ]
1>          C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27):
1>          Reason: cannot convert from 'map_alloc<U>' to 'const map_alloc<U>'
1>        with
1>        [
1>            U=std::_Tree_node<std::pair<const int,int>,std::_Default_allocator_traits<std::allocator<std::pair<const int,int>>>::void_pointer>
1>        ]
1>        and
1>        [
1>            U=std::_Container_proxy
1>        ]
1>          C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27):
1>          No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>  C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27):
1>  while trying to match the argument list '(map_alloc<U>)'
1>        with
1>        [
1>            U=std::_Tree_node<std::pair<const int,int>,std::_Default_allocator_traits<std::allocator<std::pair<const int,int>>>::void_pointer>
1>        ]
1>C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,27):
1>the template instantiation context (the oldest one first) is
1>  C:TempConsoleApplication4malloc_testeralloc_tester.cpp(34,50):
1>  see reference to class template instantiation 'std::map<int,int,std::less<int>,alloctor>' being compiled
1>  C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includemap(72,20):
1>  see reference to class template instantiation 'std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>' being compiled
1>        with
1>        [
1>            _Kty=int,
1>            _Ty=int,
1>            _Pr=std::less<int>,
1>            _Alloc=alloctor
1>        ]
1>  C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1071,6):
1>  while compiling class template member function 'std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::~_Tree(void) noexcept'
1>        with
1>        [
1>            _Kty=int,
1>            _Ty=int,
1>            _Pr=std::less<int>,
1>            _Alloc=alloctor
1>        ]
1>      C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includemap(369,1):
1>      see the first reference to 'std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::~_Tree' in 'std::map<int,int,std::less<int>,alloctor>::~map'
1>        with
1>        [
1>            _Kty=int,
1>            _Ty=int,
1>            _Pr=std::less<int>,
1>            _Alloc=alloctor
1>        ]
1>C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1075,25): error C2530: '_Alproxy': references must be initialized
1>(compiling source file 'alloc_tester.cpp')
1>C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1076,32): error C3536: '_Alproxy': cannot be used before it is initialized
1>(compiling source file 'alloc_tester.cpp')
1>C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1076,9): error C2672: '_Delete_plain_internal': no matching overloaded function found
1>(compiling source file 'alloc_tester.cpp')
1>C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includexmemory(1135,19):
1>could be 'void std::_Delete_plain_internal(_Alloc &,_Alloc::value_type *const ) noexcept'
1>  C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1076,9):
1>  Failed to specialize function template 'void std::_Delete_plain_internal(_Alloc &,_Alloc::value_type *const ) noexcept'
1>      C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1076,9):
1>      With the following template arguments:
1>          C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.38.33130includextree(1076,9):
1>          '_Alloc=int'
1>Done building project "malloc_tester.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
========== Build completed at 1:02 and took 00,554 seconds ==========

Tested on different versions of MSVC. I’m not able to find operational example on the web.

I found one example here: https://github.com/moya-lang/Allocator/tree/master

The same issue, the same compiler’s error.

2

Answers


  1. Chosen as BEST ANSWER

    Thank you, waffentrager.

    Your answer is precise. MSVC makes me crazy. After of seveal hours of investigation I found almost the same solution you proposed.

    #include <iostream>
    #include <cassert>
    #include <map>
    #include <unordered_map>
    
    template<typename T>
    class Allocator : public std::allocator<T> {
    
    public:
        Allocator() {
        }
    
        template<class Other>
        Allocator(const Allocator<Other>& _Right) {}
    
        inline typename std::allocator<T>::pointer allocate(typename std::allocator<T>::size_type n, typename std::allocator<void>::const_pointer = 0) {
            T* ret_val = nullptr;
            // custom allocator here...
            return ret_val;
        }
    
        inline void deallocate(typename std::allocator<T>::pointer p, typename std::allocator<T>::size_type n) {
            // custom delete here.
        }
    
        template<typename U>
        struct rebind {
            typedef Allocator<U> other;
        };
    
    };
    
    
    int main() {
    
        int test_cnt = 5;
    
        {
            std::map<int, int, std::less<int>, Allocator< std::pair<const int, int> > > tester_map;
            for (int i(0); i < 100; ++i) {
                tester_map[i * i * i] = i;
            }
            tester_map.clear();
        }
    
        {
            std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, Allocator< std::pair<const int, int> > > tester_unmap;
            for (int i(0); i < 100; ++i) {
                tester_unmap[i * i * i] = i;
            }
            tester_unmap.clear();
        }
    
        return 0;
    }
    

  2. For some reason the msvc compiler cannot generate a template constructor for your class in debug mode, you can switch visual studio to release mode or add
    class constructor definitions

    map_alloc() = default;
    
    template<class A>
    map_alloc(const map_alloc<A>&) noexcept {}
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search