1

I have some issues with map/unordered_map and custom allocator my allocator looks like this, according to documentation of visual studio. I derived my allocator from base type to ensure all template types like allocator::value_type is set correctly.

template <class T>
class std_allocator : public std::allocator<T> {
   public:
    std_allocator() noexcept;
    std_allocator(const std_allocator& aOther) noexcept;
    template <class O>
    std_allocator(const std_allocator<O>& aOther) noexcept;

   public:
    void deallocate(T* const aPtr, const size_t aCount);
    T* allocate(const size_t aCount);
};

now i defined a my unordered map:

class Test {
   private:
    std::unordered_map<const SomeObject*,
                       void*,
                       std::hash<const SomeObject*>,
                       std::equal_to<const SomeObject*>,
                       std_allocator<std::pair<const SomeObject*, void*>>>
        mData;
};

no i got the following compiler error: :\Development\Microsoft\Visual Studio 2019\VC\Tools\MSVC\14.28.29333\include\list(784,49): error C2338: list<T, Allocator> requires that Allocator's value_type match T (See N4659 26.2.1 [container.requirements.general]/16 allocator_type) Either fix the allocator value_type or define _ENFORCE_MATCHING_ALLOCATORS=0 to suppress this diagnostic.

from the unodered_map header the template looks like this

template <class _Kty, class _Ty, class _Hasher = hash<_Kty>, class _Keyeq = equal_to<_Kty>,
    class _Alloc = allocator<pair<const _Kty, _Ty>>>

from my point of view it looks correct. I also tried using a key without "const" except for the pair definition in allocator. the error says that I may disable the error by defining a constant but I guess that would be not a good idea. can some give some advice here?

Cheers

2
  • I am not sure that you have defined all the needed member functions, I seem to remember there need to be a lot more. Commented Nov 14, 2020 at 19:44
  • According to the c++17 documentation you just need allocate and deallocate plus several c'tors. All other functions are marked as deprecared and will be removed in c++20. I use the same allocator in vectors and it works without issues Commented Nov 14, 2020 at 19:52

1 Answer 1

1

The key detail:

class _Alloc = allocator<pair<const _Kty, _Ty>>>

The const part is the key. The key itself must be constant, which is not the same as a pointer to a constant object. There's a difference between a pointer to a constant object, and constant pointer to a (possibly const) object.

Your map definitely appears to be keyed by a pointer to a constant object. gcc 10 compiles this:

#include <memory>
#include <unordered_map>

template <class T>
class std_allocator : public std::allocator<T> {
   public:
    std_allocator() noexcept;
    std_allocator(const std_allocator& aOther) noexcept;
    template <class O>
    std_allocator(const std_allocator<O>& aOther) noexcept;

   public:
    void deallocate(T* const aPtr, const size_t aCount);
    T* allocate(const size_t aCount);
};

class SomeObject {};

class Test {
   private:
    std::unordered_map<const SomeObject*,
                       void*,
                       std::hash<const SomeObject*>,
                       std::equal_to<const SomeObject*>,
                       std_allocator<std::pair<const SomeObject* const, void*>>>
        mData;
};
Sign up to request clarification or add additional context in comments.

1 Comment

yes I see the const is key here. putting an additonal const to make the object const and not the pointer works. thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.