Date: Sat, 23 May 2026 09:46:10 +0200
You don't want to count % or the number of scopes, especially if some scopes don't have separate braces.
-----Ursprüngliche Nachricht-----
Von:Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]>
Gesendet:Sa 23.05.2026 09:37
Betreff:Re: [std-proposals] return value lives until end of scope
An:std-proposals_at_[hidden];
CC:Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>;
On Thursday, May 21, 2026, Jonathan Wakely wrote:
Yeah, I don't want spooky changes to the lifetime model and how it interacts with scopes to happen implicitly based on something far away on the function declaration. If somebody adds __persistent to a declaration, it silently changes the meaning of existing callers. No thanks.
What if we were to move the 'mark' to the calling site. Perhaps a unary operator? So the following:
int main(void)
{
%async(Func);
}
would be the same as:
int main(void)
{
auto dummy = async(Func);
}
Of course this begs the question, what about loops?
for ( unsigned i = 0u; i < N; ++i ) %async(Func);
Well I think in the above line, the scope of the return value should be to the nearest preceding {, meaning that after the loop has finished, you have N objects on the stack as the N threads run concurrently (implemented by the compiler by calling 'alloca' inside the loop with linked list).
But what if the loop has a curly-braced body?
for ( unsigned i = 0u; i < N, ++i )
{
%async(Func);
Log("new thread started");
}
In the above code, the return value from 'async' will be destroyed at the }, meaning the threads would run consecutively rather than concurrently. If you want it to persist up one level, then you double it:
for ( unsigned i = 0u; i < N, ++i )
{
%%async(Func);
Log("new thread started");
}
And if you want it to persist up another level above that, you triple it:
for ( unsigned i = 0u; i < ROWS; ++i )
{
for ( unsigned j = 0u; j < COLS; ++j )
{
%%%async(Func);
Log("new thread started");
}
}
This could allow some really cool stuff to happen, for instance let's say we were to give 'std::mutex' a method as follows:
lock_guard<mutex> mutex::autolock(void)
We could then lock a mutex as follows:
mutex m;
int main(void)
{
m.%autolock(); // or: %m.autolock() ?
DoSomething();
}
We could expand the scope of the lock:
int main(void)
{
if ( a )
{
if ( b || c )
{
m.%%%autolock(); // or: %%%m.autolock() ?
}
}
DoSomething();
}
In any function body that contains use of %% or %%%, the compiler would have to allocate space on the stack upon entering the function in order to manage the might-or-might-not-be-created objects. This would involve the use of 'alloca' along with memory addresses of destructors that need to run.
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2026-05-23 07:48:54
