Would it have to be a language feature?
Can't you just define an object managing a linked list with alloca? And calling a member function to append a new object?
If you define the object in the most-outer scope of the function, it would live until the function returns and could free the other objects (wait for the futures) in its constructor.
Why is new syntax needed?
-----Ursprüngliche Nachricht-----
Von: Frederick Virchanza Gotham via Std-Proposals <std-proposals@lists.isocpp.org>
Gesendet: Mo 01.06.2026 16:44
Betreff: [std-proposals] Function-bound objects with unary operator %
An: std-proposals <std-proposals@lists.isocpp.org>;
CC: Frederick Virchanza Gotham <cauldwell.thomas@gmail.com>;
First I'll introduce the initial motivation behind this feature. The
function 'std::async' returns an 'std::future' object, and the
destructor of 'future' blocks until the spawned thread ends. So if you
had code such as the following:
for ( unsigned i = 0u; i < rows; ++i )
for ( unsigned j = 0u; j < cols; ++j )
std::async( EntryPoint );
Instead of running (rows*cols) threads concurrently, the above code
snippet will run the threads consecutively, as you can see in the
following GodBolt:
https://godbolt.org/z/h3Y4f1jGn
You can see in the above GodBolt that the entire program execution
time is approximately 1 second.
But if we apply the unary operator '%' as follows:
for ( unsigned i = 0u; i < rows; ++i )
for ( unsigned j = 0u; j < cols; ++j )
%std::async( EntryPoint );
we can extend the lifetime of any PRvalue until the end of the
function. The two variables, 'rows' and 'cols', don't even have to be
compile-time constants, as this new feature uses 'alloca' under the
hood to allocate space for them on the stack. So now the execution
time is down to 64 milliseconds:
https://godbolt.org/z/PGqW45nG9
When the function exits, either by a 'return' statement or the
throwing of an exception, the destructors of function-bound objects
are executed in the reverse order of their construction. This is
achieved under the hood by means of traversing a linked list stored on
the stack (which again was allocated with 'alloca').
So what is this feature good for? Well you can spontaneously lock a
mutex at any point in a function:
void Func(void)
{
if ( a )
{
if ( b )
{
if ( c )
{
%lock_guard{ my_global_mutex };
}
}
}
DoSomething();
}
Here is the feature thoroughly torture-tested:
https://godbolt.org/z/aMob4Yndq
And here is the entire compiler patch up on Github:
https://github.com/healytpk/gcc-thomas-healy/commit/tag_classalloca
Personally I think function-bound objects are pretty cool. And you should too.
--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals