As you know in C++, if a temporary object is bound to a local reference, then the lifetime of the temporary is extended till the end of the scope.
But what happens if one performs a cast with a temporary or some other operation, e.g.:
#include <iostream>
struct S
{
virtual ~S() { std::cout << "~S() "; }
};
struct U : S {};
int main()
{
// this temporary is destroyed in this line in GCC, and at the end in Clang
[[maybe_unused]] auto && u = dynamic_cast<const U&>( static_cast<const S&>( U{} ) );
std::cout << ". ";
// this temporary is destroyed in this line in Clang, and at the end in GCC
[[maybe_unused]] auto && s = *&static_cast<const S&>( S{} );
std::cout << ". ";
}
Here it is clear that both u
and s
reference corresponding temporary objects, still Clang and GCC prolong the lifetime of one of the temporaries only, and do not agree on which one: https://gcc.godbolt.org/z/onWKaq8MG
Are both compilers within their rights, or one of the compilers (or both) behave incorrectly?
I think Clang is correct.
The lifetime of the temporary in the 1st case should be extended.
- a const_cast, static_cast, dynamic_cast, or reinterpret_cast conversion without a user-defined conversion that converts one of these expressions to the glvalue refers to the object designated by the operand, or to its complete object or a subobject thereof (an explicit cast expression is interpreted as a sequence of these casts),
No user-defined conversion happens here, the lifetime should be extended.
For the 2nd case, the expression *&...
is not included in the cases extending lifetime, the temporary should be destroyed after the full expression immediately.
BTW: Gcc seems behaving differently with dynamic_cast
only. Changing the dynamic_cast
in the 1st case to static_cast
, reinterpret_cast
, or c-style conversion lifetime gets extended.