c++c++17alignmentdeprecatedallocator

C++ rebind allocator with two template parameter


I'm writing an allocator that takes alignment as a template parameter also the alignment:

template<typename T, std::align_val_t alignment>
class AlignedAllocator {
public:
  using value_type = T;
  using align_type = std::size_t;

  constexpr AlignedAllocator() noexcept = default;
  constexpr AlignedAllocator(const AlignedAllocator&) noexcept = default;
  template<typename U> constexpr AlignedAllocator(const AlignedAllocator<U, alignment>&) noexcept {}

  constexpr std::size_t align() noexcept
  {
    return static_cast<std::size_t>(alignment);
  }

  [[nodiscard]]
  value_type* allocate(std::size_t n)
  {
    return reinterpret_cast<value_type*>(::operator new[](n, alignment));
  }

  void deallocate(value_type* ptr, std::size_t)
  {
    ::operator delete[](ptr, alignment);
  }
};

Problems come when I try to use std::allocator_traits methed rebind since it seems to be able to manage just one parameter, the type T. This makes my allocator non compatible with standard container library:

std::vector<AlignedAllocator<int, std::align_val_t{64}> 

does not compile. A way out would be to add

template<typename U> {                                                                                                               
struct rebind {                                                                                                                       
  using other = AlignedAllocator<U, alignment>;                                                                                       
};

this makes the code compile. However the rebind struct is deprecated in c++17 and removed in c++20.

QUESTION

Any suggestion to make my code work without using deprecated features? One would be to initialize the allocator with the alignment but I would like to keep this parameter in the type.


Solution

  • However the rebind struct is deprecated in c++17 and removed in c++20.

    The member rebind of std::allocator is removed because the default works fine for std::allocator. This is irrelevant to your allocator, which needs to provide this struct in order to meet the Allocator requirements.

    [allocator.requirements.general]/18, emphasis mine:

    If Allocator is a class template instantiation of the form SomeAllocator<T, Args>, where Args is zero or more type arguments, and Allocator does not supply a rebind member template, the standard allocator_traits template uses SomeAllocator<U, Args> in place of Allocator​::​rebind<U>​::​other by default. For allocator types that are not template instantiations of the above form, no default is provided.

    You should provide rebind in your allocator, as expected by std::allocator_traits.