6

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!

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
wanghan02
  • 1,227
  • 7
  • 14
  • The result is an xvalue of type `A`; the output should be the same as `std::move(a).foo();` – M.M Nov 19 '18 at 12:31
  • It should be `A&&.foo()` as per [this answer](https://stackoverflow.com/a/17130847/1505939) – M.M Nov 19 '18 at 12:34
  • 2
    Yes clang is correct. MSVC is wrong to make a copy. I posted a bug report for gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88103 – Oliv Nov 19 '18 at 21:14
  • 1
    Somewhat related [question here](https://stackoverflow.com/q/53328407/1708801) where gcc also gets it incorrect. – Shafik Yaghmour Nov 20 '18 at 05:07

1 Answers1

1

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.

Fedor
  • 17,146
  • 13
  • 40
  • 131