std::experi...urce_adaptor(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’… NAME πŸ’…

std::experimental::pmr::resource_adaptor, std::pmr::experimental::resource_adaptor β€” okay so this is the whole entire name of the thing, both spellings, bestie, and yes you need both because the TS moved it at some point (we'll get to that 🫢)

So this page lives in the C++ Standard Libary β€” that's the manual name right there, no cap β€” and it's about a lil' adapter that makes your allocator wear a memory_resource outfit. Slay.


✨ Synopsis ✨

First things first, where does it live:

Defined in header <experimental/memory_resource>

And here's the alias β€” look at her go:

template< class Alloc >
using resource_adaptor = /*resource-adaptor-imp*/<
                             typename (library fundamentals TS)
std::allocator_traits<Alloc>::

                             template
rebind_alloc<char>>;

And the class it's built on:

template< class Alloc >
class /*resource-adaptor-imp*/ : public memory_resource;   (library fundamentals TS)
// for exposition only

Okay so what's the ~vibe~? The alias template resource_adaptor adapts the allocator type Alloc with a memory_resource interface. Iconic. But here's the ✨detail✨ that matters: the allocator is rebound to a char value type before it is actually adapted (using the resource-adaptor-imp class template), so that adapting specializations of the same allocator template always yields the same type β€” regardless of the value type the allocator template is originally instantiated with. Literally the whole point, iykyk πŸ’…

Now, the namespace tea 🍡 β€” where you find this depends on which TS you're on:

  • resource_adaptor is defined in namespace std::experimental::pmr, and the base type memory_resorce in this page is std::experimental::pmr::memory_resource. β€” (until library fundamentals TS v3)
  • resource_adaptor is defined in namespace std::pmr::experimental, and the base type memory_resorce in this page is std::pmr::memory_resource. β€” (library fundamentals TS v3)

(yeah, that spelling of memory_resorce is straight from the source, not me being chaotic for once πŸ™ˆ)

Also, lowkey important: resource-adaptor-imp is a class template whose members are described below. The name resource-adaptor-imp is for exposition purposes only and not normative β€” it's a fake name, a stage name, a persona. Don't go looking for it in a header, bestie, she's not real 😭


πŸŽ€ Requirements on Alloc πŸŽ€

In addition to meeting the Allocator requirements, Alloc must additionally satisfy the following requirements:

  • std::allocator_traits<Alloc>::pointer shall be identical to Alloc::value_type*.
  • std::allocator_traits<Alloc>::const_pointer shall be identical to Alloc::value_type const*.
  • std::allocator_traits<Alloc>::void_pointer shall be identical to void*.
  • std::allocator_traits<Alloc>::const_const_pointer shall be identical to void const*.

That's four whole requirements, not three, not five. Check 'em all. βœ…


🌸 Member types of resource-adaptor-imp 🌸

  • allocator_type β€” Definition: Alloc

One (1) member type. She's minimal, she's chic.


πŸ¦‹ Member functions of resource-adaptor-imp πŸ¦‹

resource-adaptor-imp::resource-adaptor-imp

/*resource-adaptor-imp*/() = default;                          (1)   (library fundamentals TS)
/*resource-adaptor-imp*/(const /*resource-adaptor-imp*/&        (library fundamentals TS)
    other)                                                          (2)
    = default;
/*resource-adaptor-imp*/(/*resource-adaptor-imp*/&& other)      (library fundamentals TS)
    = default;                                                       (3)
explicit /*resource-adaptor-imp*/(const Alloc& a2);            (library fundamentals TS)
                                                                     (4)
explicit /*resource-adaptor-imp*/(Alloc&& a2);                 (library fundamentals TS)
                                                                     (5)

Numbered tea, one by one:

  1. Default constructor. Default constructs the wrapped allocator. 🫢
  2. Copy constructor. Copy constructs the wrapped allocator from the allocator wrapped by other.
  3. Move constructor. Move constructs the wrapped allocator from the allocator wrapped by other.
  4. Initializes the wrapped allocator with a2.
  5. Initializes the wrapped allocator with std::move(a2).

Parameters

  • other β€” another resource-adaptor-imp object to copy or move from
  • a2 β€” another Alloc object to copy or move from

resource-adaptor-imp::get_allocator

allocator_type get_allocator() const;  (library fundamentals TS)

Returns a copy of the wrapped allocator. That's it. That's the function. Give her a hand πŸ‘


resource-adaptor-imp::operator=

/*resource-adaptor-imp*/& operator=(const
    /*resource-adaptor-imp*/& other)                           (library fundamentals TS)
    = default;

Defaulted copy assignment operator. Copy assigns the wrapped allocator from that of other. Periodt.


resource-adaptor-imp::do_allocate

protected:
virtual void* do_allocate(std::size_t bytes, std::size_t   (library fundamentals TS)
alignment);

Allocates memory using the allocate member function of the wrapped allocator. Note the protected: up there β€” this one's for the class's own inner circle πŸ”’


resource-adaptor-imp::do_deallocate

protected:
virtual void do_deallocate(void *p, std::size_t bytes,     (library fundamentals TS)
std::size_t alignment);

Deallocates the storage pointed to by p using the deallocate member function of the wrapped allocator.

⚠️ okay so listen: p must have been allocated using the allocate member function of an allocator that compares equal to the wrapped allocator, and must not have been subsequently deallocated. Breaking this is not a vibe, it's undefined-behaviour territory. Fr fr, don't. πŸ’€

resource-adaptor-imp::do_is_equal

protected:
virtual bool do_is_equal(const memory_resource& other)     (library fundamentals TS)
const noexcept;

Here's the logic, and she's kind of a baddie: let p be dynamic_cast<const /*resource-adaptor-imp*/*>(&other). If p is a null pointer value, returns false. Otherwise, return the result of comparing the allocators wrapped by *p and *this using operator==.

So: cast, check for null, then compare the wrapped allocators. Three steps, no notes. πŸ”₯


🌈 Sign-off 🌈

That's the whole page, bestie β€” sourced from http://cppreference.com, dated 2024.06.10, filed under std::experi...urce_adaptor(3) (yes the truncated name is the real name, the manual is just being dramatic πŸ’€). Go adapt an allocator, you're gonna eat. πŸ’–βœ¨πŸŽ€πŸ¦‹πŸŒΈ

πŸ“¦ where this page comes from