C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Function-bound objects with unary operator %

From: Sebastian Wittmeier <wittmeier_at_[hidden]>
Date: Mon, 1 Jun 2026 16:49:53 +0200
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_at_[hidden]> Gesendet:Mo 01.06.2026 16:44 Betreff:[std-proposals] Function-bound objects with unary operator % An:std-proposals <std-proposals_at_[hidden]>; CC:Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>; 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_at_[hidden] https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2026-06-01 14:53:00