Reputation: 1317
Say we have a ternary operator with 2 xvalue operands.
struct A {
A() { std::cout<<"A ctor"<<std::endl; }
~A() { std::cout<<"A dtor"<<std::endl; }
A(A const&) { std::cout<<"A copy ctor"<<std::endl; }
A(A&&) { std::cout<<"A move ctor"<<std::endl; }
void foo() & { std::cout<<"A&.foo()"<<std::endl; }
void foo() const& { std::cout<<"A const&.foo()"<<std::endl; }
void foo() && { std::cout<<"A&&.foo()"<<std::endl; }
void foo() const&& { std::cout<<"A const&&.foo()"<<std::endl; }
};
int main()
{
A a;
A a2;
(true? static_cast<A&&>(a) : static_cast<A&&>(a2)).foo();
return 0;
}
According to cppreference conditional operator
4) If E2 and E3 are glvalues of the same type and the same value category, then the result has the same type and value category, and is a bit-field if at least one of E2 and E3 is a bit-field.
The result should be also A&& and no copy or move constructors are expected. Am I correct?
But gcc, clang and Visual Studio give different results on this.
gcc: A&.foo()
clang: A&&.foo()
VS:
A move ctor
A&&.foo()
If we cast both operand types to A const&&
, gcc will be A const&.foo()
, clang will be A const&&.foo()
, VS will be A const&&.foo()
with a copy ctor called.
Is clang the correct one on this? Thanks!
Upvotes: 7
Views: 231
Reputation: 21099
Yes, the correct output of the program execution is:
A ctor
A ctor
A&&.foo()
A dtor
A dtor
The corresponding GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88103 was fixed in GCC 7.5, 8.3, 9.1 versions. Demo: https://gcc.godbolt.org/z/6hbaW4W5q
The latest MSVC also prints correct output.
Upvotes: 1