Ternary operator with xvalue operands

231 Views Asked by At

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!

1

There are 1 best solutions below

0
On

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.