Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a custom allocator that works with MSVC [duplicate]

I have a simple custom allocator class to be used for std::vector, looking like this:

#include <type_traits>
#include <limits>
#include <new>
#include <vector>

/** Constrains a value to be an integer which is some power of two */
template <auto value>
concept powerOfTwoInt = std::is_integral_v<decltype (value)> && (value & (value - 1)) == 0;

template <size_t value>
requires (powerOfTwoInt<value>)
constexpr size_t nextMultipleOf (size_t numElements)
{
    return (numElements + value - 1) & -value;
}

template <typename ElementType, size_t alignmentInBytes>
requires (alignmentInBytes >= alignof (ElementType) && powerOfTwoInt<alignmentInBytes>)
class AlignedAllocator
{
public:
    using value_type = ElementType;

    using is_always_equal = std::true_type;

    constexpr bool operator== (const AlignedAllocator& other) noexcept
    {
        return true;
    }

    AlignedAllocator (const AlignedAllocator& other) = default;

    [[nodiscard]] ElementType* allocate (size_t nElementsToAllocate)
    {
        if (nElementsToAllocate > std::numeric_limits<size_t>::max () / sizeof (ElementType))
        {
            throw std::bad_array_new_length ();
        }

        const auto nBytesToAllocate = nextMultipleOf<8> (nElementsToAllocate * sizeof (ElementType));

        return reinterpret_cast<ElementType*> (::operator new[] (nBytesToAllocate, std::align_val_t (alignmentInBytes)));
    }

    void deallocate (ElementType* allocatedPointer, [[maybe_unused]] size_t nBytesAllocated)
    {
        ::operator delete[] (allocatedPointer, std::align_val_t (alignmentInBytes));
    }
};

When compiling with MSVC 19.33 and C++20 I get weird compile errors, see here. If I didn't get anything wrong, I implemented all the non-optional requirements for an Allocator, according to cppreference.com. It seems to me that the errors are somehow related to the rebind feature, which however is optional according to the document linked above. I want to keep my implementation as simple as possible, so can anyone tell me what MSVC wants me to implement here in order to solve that error?

The same implementation works fine with clang.

like image 200
PluginPenguin Avatar asked Oct 18 '25 03:10

PluginPenguin


1 Answers

You need a custom rebind. It's only optional if the allocator's first template argument is the element type, followed by any number of type template parameters. But you have a non-type template parameter in there.

template <typename T>
struct rebind
{
    using other = AlignedAllocator<T, alignmentInBytes>;
};

You also need a constructor, preferably a default constructor.

like image 161
HolyBlackCat Avatar answered Oct 20 '25 18:10

HolyBlackCat