具有 xvalue 操作数的三元运算符

Han*_*Han 7 c++ c++11 c++14 c++17 value-categories

假设我们有一个带有 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;
}
Run Code Online (Sandbox Code Playgroud)

根据cppreference条件运算符

4) 如果 E2 和 E3 是相同类型和相同值类别的左值,则结果具有相同类型和值类别,并且如果 E2 和 E3 至少其中之一是位字段,则结果是位字段。

结果也应该是 A&& 并且不需要复制或移动构造函数。我对么?

但 gcc、clang 和 Visual Studio 对此给出了不同的结果。

海湾合作委员会:A&.foo()

铛:A&&.foo()

对比:

A move ctor
A&&.foo()
Run Code Online (Sandbox Code Playgroud)

如果我们将两种操作数类型都转换为A const&&,gcc 将为A const&.foo(),clang 将为A const&&.foo(),VS 将带有A const&&.foo()一个名为的复制构造函数。

clang 是正确的吗?谢谢!

Fed*_*dor 1

是的,程序执行的正确输出是:

A ctor
A ctor
A&&.foo()
A dtor
A dtor
Run Code Online (Sandbox Code Playgroud)

相应的 GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88103已在 GCC 7.5、8.3、9.1 版本中修复。演示: https: //gcc.godbolt.org/z/6hbaW4W5q

最新的 MSVC 还可以打印正确的输出。