Skip to content

<xstd/misc/concepts/simple_allocator.hpp>

xstd::simple_allocator

template<class Alloc>
concept simple_allocator =
  requires(Alloc alloc, size_t n) {
    { *alloc.allocate(n) } -> same_as<typename Alloc::value_type&>;
    { alloc.deallocate(alloc.allocate(n), n) };
  } and copy_constructible<Alloc> and equality_comparable<Alloc>;

An allocator, to the syntax the working draft checks. The definition is its exposition-only simple-allocator, [allocator.requirements.general]/99, word for word, under a name users can spell.

Semantic requirements

A type models it if it meets the requirements of [allocator.requirements.general].

Example

#include <xstd/misc/concepts/simple_allocator.hpp> // simple_allocator
#include <array>                                   // array
#include <cstddef>                                 // byte
#include <iostream>                                // boolalpha, cout
#include <memory>                                  // allocator
#include <memory_resource>                         // memory_resource, monotonic_buffer_resource, polymorphic_allocator

// Stores a value in storage from any allocator, reads it back and returns the storage.
template<xstd::simple_allocator Alloc>
[[nodiscard]] auto round_trip(Alloc alloc, typename Alloc::value_type value)
        -> typename Alloc::value_type
{
        auto* const storage = alloc.allocate(1);
        *storage            = value;
        auto const read     = *storage;
        alloc.deallocate(storage, 1);
        return read;
}

auto main() -> int
{
        auto buffer   = std::array<std::byte, 256>();
        auto resource = std::pmr::monotonic_buffer_resource(buffer.data(), buffer.size());

        std::cout << round_trip(std::allocator<int>(), 1) << '\n';
        std::cout << round_trip(std::pmr::polymorphic_allocator<int>(&resource), 2) << '\n';

        // A memory resource hands out bytes, not elements, so it is no allocator.
        std::cout << std::boolalpha;
        std::cout << "simple_allocator<std::allocator<int>> is " << xstd::simple_allocator<std::allocator<int>> << '\n';
        std::cout << "simple_allocator<std::pmr::polymorphic_allocator<int>> is " << xstd::simple_allocator<std::pmr::polymorphic_allocator<int>> << '\n';
        std::cout << "simple_allocator<std::pmr::memory_resource*> is " << xstd::simple_allocator<std::pmr::memory_resource*> << '\n';
}

Output:

1
2
simple_allocator<std::allocator<int>> is true
simple_allocator<std::pmr::polymorphic_allocator<int>> is true
simple_allocator<std::pmr::memory_resource*> is false

See also

Entity Relation
container_compatible_range the other exposition-only concept copied from the working draft
std::allocator_traits the standard's uniform interface to an allocator