Date: Thu, 23 May 2024 17:37:02 +0000
> in the third given example there are two (movable) candidates with overlapping lifetimes.
> Would you still consider those for RVO?
No, as RVO requires constructing the object in place, the signature of the function only specifies 1 object, and there is only 1 place for that object to be created.
If you need to create object A and B, and either of them could be returned, the compiler needs to decide which one of those objects is going to be created at the return address, as two distinct objects cannot occupy the same address.
If both A and B need to have been created before a decision can be made of which one is going to be returned, there is no way the compiler would know which of the objects to construct at the return address.
You also can not decide to tentatively RVO A and then later swap it to by moving B given that the lifetime of A has not expired after the move of B is completed.
But there is nothing that stops you from having multiple objects occupying the same address if they don’t do so simultaneously. That is why if A and B don’t have overlapping lifetimes, you would be able to tentatively RVO A and later decide not to return it, destroy A and reconstruct B in its place.
Now this is a completely different story if the compiler could optimize the condition and be able to hoist the construction of A and B.
I.e.
Imovable A;
Imovable B;
if(cond)
{
return A;
}
else
{
return B;
}
is optimized as
if(cond)
{
Imovable A;
Imovable B;
return A;
}
else
{
Imovable A;
Imovable B;
return B;
}
This would make it unambiguous as to who would be constructed at the return address, and
I would like to say that because it could it would be allowed, but…, since this is an optimization, there is no guarantee on which compiler would take it, or if they would take it and introduces room for unpredictable behavior.
And I don’t won’t to deal with that. So no.
> Possible solutions:
> - use the preprocessor (really?)
> - derive LoggedMutex from std::mutex (would change the type; only possible for non-final classes)
> - keep std::mutex as attribute within custom class (would change the type)
> - use UB (no-go)
> - call a factory method (needs RVO)
> (I would recommend changing the type to also get a message at destruction.)
If we are going to allow an extension of RVO in the language, allow an extension of RVO in the language, the point of doing so is to not have to jump through hoops to get what you want.
> Would you still consider those for RVO?
No, as RVO requires constructing the object in place, the signature of the function only specifies 1 object, and there is only 1 place for that object to be created.
If you need to create object A and B, and either of them could be returned, the compiler needs to decide which one of those objects is going to be created at the return address, as two distinct objects cannot occupy the same address.
If both A and B need to have been created before a decision can be made of which one is going to be returned, there is no way the compiler would know which of the objects to construct at the return address.
You also can not decide to tentatively RVO A and then later swap it to by moving B given that the lifetime of A has not expired after the move of B is completed.
But there is nothing that stops you from having multiple objects occupying the same address if they don’t do so simultaneously. That is why if A and B don’t have overlapping lifetimes, you would be able to tentatively RVO A and later decide not to return it, destroy A and reconstruct B in its place.
Now this is a completely different story if the compiler could optimize the condition and be able to hoist the construction of A and B.
I.e.
Imovable A;
Imovable B;
if(cond)
{
return A;
}
else
{
return B;
}
is optimized as
if(cond)
{
Imovable A;
Imovable B;
return A;
}
else
{
Imovable A;
Imovable B;
return B;
}
This would make it unambiguous as to who would be constructed at the return address, and
I would like to say that because it could it would be allowed, but…, since this is an optimization, there is no guarantee on which compiler would take it, or if they would take it and introduces room for unpredictable behavior.
And I don’t won’t to deal with that. So no.
> Possible solutions:
> - use the preprocessor (really?)
> - derive LoggedMutex from std::mutex (would change the type; only possible for non-final classes)
> - keep std::mutex as attribute within custom class (would change the type)
> - use UB (no-go)
> - call a factory method (needs RVO)
> (I would recommend changing the type to also get a message at destruction.)
If we are going to allow an extension of RVO in the language, allow an extension of RVO in the language, the point of doing so is to not have to jump through hoops to get what you want.
Received on 2024-05-23 17:37:07