Date: Mon, 20 May 2024 13:34:05 +0100
On 19/05/2024 21:28, Frederick Virchanza Gotham via Std-Proposals wrote:
> On Sunday, May 19, 2024, Jason McKesson wrote:
>>
>> Then you haven't actually fixed the problem, have you? If you believe
>> that the standard needs a way to do NRVO, then providing a "way to do
>> NRVO" that doesn't represent legal C++ code is not actually fixing the
>> problem.
>
>
> Well you can make it all legal C++ code if you tinker with the object
> files instead of the C++ source files. For example I can write the
> following function:
>
> void Func(void *const p)
> {
> auto &m = *::new(p) mutex{};
> try
> {
> m.lock();
> }
> catch(...)
> {
> m.~mutex();
> throw;
> }
> }
>
> And compile it to an object file which will export the following
> symbol: _Z4FuncPv
>
> Then all you need to do is use 'objcopy' (or a hex editor) to rename
> that symbol to: _Z4Funcv
>
> And now it behaves as though you had written:
>
> mutex Func(void)
> {
> mutex m;
> m.lock();
> return m;
> }
>
> And then in a separate translation unit, you declare the function as:
> extern mutex Func(void);
> Or . . . to make things even simpler, just define the function as
> "extern C" and then you don't have to change the linker symbol as it
> will simply be "Func".
>
> As fun and interesting as this back-and-forth is, Jason, let's get to
> the crux of the matter. There's already a lengthy paper to provide
> NRVO:
>
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2025r2.html
>
> This paper has been gathering dust for 3 years (actually a few more
> than that if you consider the previous revisions), and it's not
> because it's a bad paper. I think it hasn't had any thrust behind it
> because it's just too much grief to write it into the Standard and for
> compiler vendors to implement it. So if P2025 is going to gather dust
> past C++26, C++29, C++32 and so on, then how about we just try
> something less ambitious.
I think it's a great paper, and I think it's gathering dust for much
more banal reasons, like the original author not having the time or
motivation to update it, somebody else to have the motivation to pick it up.
I personally think it's a great paper, but one of the short-coming is
that it should require an opt-in syntax for NRVO, and that invites the
inevitable bikeshedding around syntax that can destroy any remaining
motivation from paper authors.
> A less-ambitious alternative would be to
> allow something like:
>
> mutex Func(void)
> {
> auto &m = _Retvar{};
> m.lock();
> return _Retvar;
> }
>
> I propose that the operator "_Retvar" can only be used in a function
> that returns by value. Its job is to create an object of the return
> type, and it returns a reference to the new object. Then later you
> just write "return _Retvar" to return from the function.
I think if you are going to propose a barebones solution with many
undefined behavior traps, than what should be done is to just expose the
return slot to the function body as storage, without automatically
constructing anything there. Then it's the responsibility of the
function to populate the return slot, if the function exits by exception
or to ensure that the return slot is empty, if it exits by exception.
I'm not a huge fan of this, because it's easy to misuse compared P2025,
which is already very flexible, but arguably this is simpler to implement.
Anyway, some food for thought: functions can and do reuse the return
slot multiple times, P2025 also allows this:
Widget foo(string some_arg) {
{
Widget widget(some_arg); // widget is created on return slot
if (widget.check_something()) {
return widget; // return normally...
}
} //... or destroy widget
return Widget("default"); // and return an entirely different object
}
IME clang optimizes this to use NRVO for `widget`, gcc does not.
So the return slot's occupancy can be on and off throughout the
execution of the function.
Cheers,
Lénárd
> On Sunday, May 19, 2024, Jason McKesson wrote:
>>
>> Then you haven't actually fixed the problem, have you? If you believe
>> that the standard needs a way to do NRVO, then providing a "way to do
>> NRVO" that doesn't represent legal C++ code is not actually fixing the
>> problem.
>
>
> Well you can make it all legal C++ code if you tinker with the object
> files instead of the C++ source files. For example I can write the
> following function:
>
> void Func(void *const p)
> {
> auto &m = *::new(p) mutex{};
> try
> {
> m.lock();
> }
> catch(...)
> {
> m.~mutex();
> throw;
> }
> }
>
> And compile it to an object file which will export the following
> symbol: _Z4FuncPv
>
> Then all you need to do is use 'objcopy' (or a hex editor) to rename
> that symbol to: _Z4Funcv
>
> And now it behaves as though you had written:
>
> mutex Func(void)
> {
> mutex m;
> m.lock();
> return m;
> }
>
> And then in a separate translation unit, you declare the function as:
> extern mutex Func(void);
> Or . . . to make things even simpler, just define the function as
> "extern C" and then you don't have to change the linker symbol as it
> will simply be "Func".
>
> As fun and interesting as this back-and-forth is, Jason, let's get to
> the crux of the matter. There's already a lengthy paper to provide
> NRVO:
>
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2025r2.html
>
> This paper has been gathering dust for 3 years (actually a few more
> than that if you consider the previous revisions), and it's not
> because it's a bad paper. I think it hasn't had any thrust behind it
> because it's just too much grief to write it into the Standard and for
> compiler vendors to implement it. So if P2025 is going to gather dust
> past C++26, C++29, C++32 and so on, then how about we just try
> something less ambitious.
I think it's a great paper, and I think it's gathering dust for much
more banal reasons, like the original author not having the time or
motivation to update it, somebody else to have the motivation to pick it up.
I personally think it's a great paper, but one of the short-coming is
that it should require an opt-in syntax for NRVO, and that invites the
inevitable bikeshedding around syntax that can destroy any remaining
motivation from paper authors.
> A less-ambitious alternative would be to
> allow something like:
>
> mutex Func(void)
> {
> auto &m = _Retvar{};
> m.lock();
> return _Retvar;
> }
>
> I propose that the operator "_Retvar" can only be used in a function
> that returns by value. Its job is to create an object of the return
> type, and it returns a reference to the new object. Then later you
> just write "return _Retvar" to return from the function.
I think if you are going to propose a barebones solution with many
undefined behavior traps, than what should be done is to just expose the
return slot to the function body as storage, without automatically
constructing anything there. Then it's the responsibility of the
function to populate the return slot, if the function exits by exception
or to ensure that the return slot is empty, if it exits by exception.
I'm not a huge fan of this, because it's easy to misuse compared P2025,
which is already very flexible, but arguably this is simpler to implement.
Anyway, some food for thought: functions can and do reuse the return
slot multiple times, P2025 also allows this:
Widget foo(string some_arg) {
{
Widget widget(some_arg); // widget is created on return slot
if (widget.check_something()) {
return widget; // return normally...
}
} //... or destroy widget
return Widget("default"); // and return an entirely different object
}
IME clang optimizes this to use NRVO for `widget`, gcc does not.
So the return slot's occupancy can be on and off throughout the
execution of the function.
Cheers,
Lénárd
Received on 2024-05-20 12:34:13