[libcxx-commits] [PATCH] D133638: [libc++] static_assert that rebinding the allocator works as expected

Nikolas Klauser via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Wed Oct 12 03:10:54 PDT 2022


philnik added a comment.

In D133638#3850608 <https://reviews.llvm.org/D133638#3850608>, @rupprecht wrote:

> I see. That's a surprising result of this patch, and the error message is not very clear. Is there any way a static assert could be added to make it more clear?

I'll look into that. Maybe it's possible to generate a nicer error when you try to rebind an allocator which doesn't support rebinding.

> Would this be valid way to fix up any breakages with minimal changes? It builds, but will this just hit some other conformance check later?
>
>   #include <vector>
>   
>   struct Foo {
>     int f;
>   };
>   
>   template <typename T = Foo>  // <-- Add this
>   class FooAllocator {
>    public:
>     static_assert(std::is_same_v<T, Foo>, "T must be Foo"); // <-- Add this (if desired)
>     using value_type = Foo;
>     FooAllocator() = default;
>   
>     Foo* allocate(size_t num_objects);
>   
>     void deallocate(Foo* ptr, size_t num_objects);
>   
>     bool operator==(const FooAllocator&) const { return true; }
>     bool operator!=(const FooAllocator&) const { return false; }
>   };
>   
>   void x() { std::vector<Foo, FooAllocator<>> y; } // <-- FooAllocator is now FooAllocator<>

It's still not conforming, since the containers are allowed to rebind the allocator to any type. So I wouldn't guarantee that we will never add a check to catch this kind of allocator. For the short term it would probably work, but my recommendation would be to

- Implement the allocator in a type-agnostic way, i.e. replace any `Foo`s with `T`, or
- Look into using `polymorphic_allocator` and implement a `memory_resource`

That would allow you to use the allocator more generally, instead of for a specific type. I of course don't know exactly what your allocator does and what environment you are deploying in, so these options might not be viable for you.

As a temporary work-around it might also be easier to add something like

  template <class T>
  struct rebind {
    // TODO: Allow rebinding the allocator properly
    static_assert(std::is_same_v<T, Foo>, "Rebinding this allocator to anything other than Foo does not work currently");
    using other = FooAllocator;
  };

to `FooAllocator`.

We could also look into changing it into a warning for the containers that don't actually rebind the allocator if this breaks too many people.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133638/new/

https://reviews.llvm.org/D133638



More information about the libcxx-commits mailing list