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