Тернарный оператор с операндами xvalue

Скажем, у нас есть троичный оператор с 2 операндами xvalue.

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;
}

Согласно условному оператору

4) Если E2 и E3 являются glvalues ​​одного и того же типа и той же категории значения, то результат имеет тот же тип и категорию значения и является битовым полем, если хотя бы один из E2 и E3 является битовым полем.

Результатом должен быть также A&&, и конструкторы копирования или перемещения не ожидаются. Я прав?

Но gcc, clang и Visual Studio дают разные результаты по этому вопросу.

НКА: A&.foo()

лязг: A&&.foo()

VS:

A move ctor
A&&.foo()

Если мы приведем оба типа операндов к A const&&гкк будет A const&.foo()лязг будет A const&&.foo()VS будет A const&&.foo() с копией ctor называется.

Является ли Clang правильным на этом? Спасибо!

1 ответ

Да, правильный вывод выполнения программы:

      A ctor
A ctor
A&&.foo()
A dtor
A dtor

Соответствующая ошибка GCC https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88103 была исправлена ​​в версиях GCC 7.5, 8.3, 9.1. Демо: https://gcc.godbolt.org/z/6hbaW4W5q

Последний MSVC также печатает правильный вывод.

Другие вопросы по тегам