wanghan02
wanghan02

Reputation: 1317

Ternary operator with xvalue operands

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

Answers (1)

Fedor
Fedor

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

Related Questions