First of all I want to predict the memory usage of my code, just as any responsible programmer should. This would apply even if I was not deciding to allocate my coroutine frames using placement new, as I am (see below pseudocode). Even supposing I change my mind about placement-newing all my coroutines, and thus I let the complier allocate all my coroutines on the heap, I'd still want the C++ language to tell me how much heap I'm going to eat up by that.
But, IRL, I'm targeting a high-reliability and embedded environment. There might not even be a heap, so...
struct coroutine_return_type
{
struct promise_type
{
void *operator new(std::size_t sz, char *buf, std::size_t szbuf)
{
if (sz > szbuf)
throw std::bad_alloc{};
return buf;
}
void operator delete(void *)
{
}
// ...
};
// ...
};
coroutine_return_type my_coroutine(char *, std::size_t)
{
// The arguments, char * and std::size_t,
// have been fowrarded to promise_type::operator new
// but here in the coroutine body they aren't used again...
for ( ; ; )
co_yield /* something */;
}
struct coroutine_instance_type
{
char my_coroutine_frame[ /* WHAT? */ ];
coroutine_return_type my_coroutine_instance;
coroutine_instance_type()
: my_coroutine_instance{my_coroutine(my_coroutine_frame, sizeof(my_coroutine_frame))}
{
// ...
}
// ...
};
WHAT I WANT
I want a complie-time expression to return an upper bound on my coroutine size, to replace /* WHAT? */.
STUPID SOLUTION
There's an obviously stupid way to (not quite) do what I want:
Subclass std::bad_alloc. Then
throw std::bad_alloc{}in myoperator newbecomesthrow std::my_bad_alloc{sz}. The catch block can callmy_bad_alloc_instance.get_parameter()to learn whatszwas insideoperator new.Call
my_coroutine(nullptr, 0)and catch the exception.
What's stupid about this (nonexhaustive list):
It's not a compile-time expression, because it has to "return" its value using a throw and throw can never be used in a complie-time expression. But the replacement for /* WHAT? */ in my pseudocode needs to be a compile-time expression.
It's a sample, not an upper bound. Suppose the actual, allocated size of the coroutine frame depends on conditions at run-time. (Now, I don't anticipate that different coroutine sizes for different run-time conditions, will ever actually occur in my IRL applcation, but according to the C++ standard it seems to be possible.) In that case, it's insufficient to just learn what size is actually passed to operator new. The required expression would have to return, instead, an upper bound on what could be passed to operator new.
So, in summary:
SUMMARY OF THE QUESTION
What tools does the C++ language provide to query the size of a coroutine frame? The ideal tool should be a compile-time expression for allocating non-heap memory to the coroutine, or alternatively, the same tool would serve as well for bounding the amount of heap.