std::genera...:operatornew(3)

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

πŸ’– NAME πŸ’–

std::generator::promise_type::operatornew β€” bestie, it's literally the allocation operator for the promise type of std::generator, and yes it's as extra as it sounds πŸ’…

So real quick, this page lives in the C++ Standard Library manual, section 3 β€” that's the std::genera...:operatornew(3) header up top, folded in here so we can just vibe πŸŽ€


✨ Synopsis ✨

Okay so there are three overloads and they're all since C++23, periodt πŸ¦‹

Overload (1) β€” the no-allocator-argument one, lowkey the simplest:

void* operator new( std::size_t size )

    requires std::same_as<Allocator, void> ||
             std::default_initializable<Allocator>;

(1) (since C++23)

Overload (2) β€” the one where you hand it an allocator with std::allocator_arg_t:

template< class Alloc, class... Args >

    requires std::same_as<Allocator, void> ||
             std::convertible_to<const Alloc&, Allocator>

void* operator new( std::size_t size, std::allocator_arg_t,

                    const Alloc& alloc, const Args&... );

(2) (since C++23)

Overload (3) β€” same energy as (2) but with an extra const This& in there:

template< class This, class Alloc, class... Args >

    requires std::same_as<Allocator, void> ||
             std::convertible_to<const Alloc&, Allocator>

void* operator new( std::size_t size, const This&,
                    std::allocator_arg_t,

                    const Alloc& alloc, const Args&... );

(3) (since C++23)


🌸 Description 🌸

So what's the actual tea? It allocates size bytes of uninitialized storage using either the default allocator or the user-provided one. Slay πŸ’…

Let's define our girls, because the standard does the whole "let A be…" thing and honestly, iykyk:

Let A be

  • Allocator, if it is not void,
  • Alloc for (2,3), or
  • std::allocator<void> otherwise.

Let B be std::allocator_traits<A>::template rebind_alloc<U> where U is an unspecified type whose size and alignment are both __STDCPP_DEFAULT_NEW_ALIGNMENT__ πŸ‘‘

Then it initializes an allocator b of type B with:

  1. A(),
  2. and 3) A(alloc).

Uses b to allocate storage for the smallest array of U sufficient to provide storage for a coroutine state of size size, and unspecified additional state necessary to ensure that operator delete can later deallocate this memory block with an allocator equal to b. Fr fr, that extra unspecified state is doing main character work so your delete doesn't get left on read 😭

⚠️ Note, bestie, do not skip this: std::allocator_traits<B>::pointer must be of a pointer type, otherwise the behavior is undefined πŸ’€ Like, actually undefined. Not cute. Not iconic. Just don't.

πŸŽ€ Parameters πŸŽ€

  • size β€” the size of the storage to allocate. that's the byte count, babe πŸ“
  • alloc β€” a user provided allocator of type Alloc. your very own allocator, hand-picked 🫢

⭐ Return value ⭐

A pointer to the allocated storage. boom. that's it. that's the pointer ✨


πŸ”₯ Exceptions πŸ”₯

1-3) May throw. all three of them. every single one. no cap πŸ™ˆ


🧚 little reminder to keep your std::allocator_traits<B>::pointer a real pointer type, because undefined behavior is not the vibe check you want to fail πŸ’€

and that's the whole page, bestie!! 🌈 this iconic lil' page came to you from http://cppreference.com, dated 2024.06.10 β€” mwah, ily, go write some coroutines πŸ’œπŸŽ€

πŸ“¦ where this page comes from