C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Custom call convention per type

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Thu, 28 Jul 2022 18:48:00 -0400
On Thu, Jul 28, 2022 at 5:26 PM Marcin Jaczewski via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> Currently there are multiple problems linked to lifetime of function parameters.
> Simply current default behavior does not fit all corner cases.
>
> Example is `std::unique` that generates subpar code because the call
> site is a firewall that
> prevents the compiler to see at once destructor and move operation.

I don't understand what you mean by this. Are you talking about the
movement of the elements in the range, since the destruction of the
moved-from elements (if it happens at all) is handled by the
(eventual) caller? If so, your suggestion can't solve that problem.
The problem you're describing is not about parameters; it's about the
*contents* of those parameters.

> Now what if we op-in to allow a given type to have lifetime handled differently?
>
> Image we add new contextual keyword like:
> ```
> class Type arg_destructor_in_callee
> {
> };
> ```
> Now when the function `void foo(Type arg)` is called, the object `arg`
> will be destroyed
> in the body of `foo` not by the caller. This will make for compiler
> easy to see if object was
> moved before the destructor call and then if the destructor was inlined
> then it could remove it all. This will work great with `bitcopies` or
> `Trivially Relocatable` types.

First, making this a property of the type instead of the function
makes no sense. After all, the problem is caused (I guess?) by what
the function is doing. This is not something inherent to the nature of
an object type; it's a part of how an object is being used.

Second, this is yet another "trivially relocatable" proposal in yet
another disguise. I really wish people would stop trying to break this
problem down into little bits in the hopes that they can sneak one of
them past the committee.

> This will of course affect ABI (this is why keyword not attribute) and
> change order of destructor calls.
> This could be new reference type (`&&&`??) but this probably will be
> big burden on all generic
> code as we will need another case to handle this.

Oh, that's why you want it on the type. So that you can dodge the
forwarding problem.

> Another interesting side effect is that even if this feature need
> op-in you can always wrap arbitrary object into type with this did
> this and benefice from this, like:
>
> ```
> template<typename T>
> struct Wrapper arg_destructor_in_callee
> {
> Wrapper (T&& t) : data{ std::move(t) } //implicit constructor
> {
> }
> T data;
> };
> template<typename T>
> void foo(Wrapper<T> arg)
> {
> }
>
> int main()
> {
> foo(1);
> foo(std::make_unique<int>());
> }
> ```
> And no destructor will be directly called by `main`.

So really, you could do this purely as a library feature. You fashion
a type called "internal_relocate<T>" or somesuch which is
constructible from a `T`. But its destructor doesn't call the
destructor of the `T` it holds. It's up to the implementation of the
function to invoke the destructor by using a member of
`internal_relocate` or somesuch. And any function which wants to take
advantage of this would take an `internal_relocate` object as a
parameter.

> And this brings me to the opposite problem, that in some cases I do
> not want to temporarily be destroyed by callee.

What does that mean? Parameters to a function don't get destroyed "by
the callee". Ever. If you're talking about the return value, then
there are already proposals to allow for named RVO, though they have
(reasonable) limits on the usage of the return value object.

> Then we could define
> another keyword `arg_destructor_in_caller` that would force all ABI to
> pass this temporary as a hidden pointer.
>
> Would this approach be useful?
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2022-07-28 22:48:12