【问题标题】:Ternary operator with xvalue operands具有 xvalue 操作数的三元运算符
【发布时间】:2018-11-19 11:59:49
【问题描述】:

假设我们有一个带有 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;
}

根据cppreference条件运算符

4) 如果 E2 和 E3 是相同类型和相同值的泛左值 类别,则结果具有相同的类型和值类别,并且是 如果 E2 和 E3 中的至少一个是位域,则为位域。

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

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

gcc:A&amp;.foo()

叮当声:A&amp;&amp;.foo()

对比:

A move ctor
A&&.foo()

如果我们将两种操作数类型都转换为A const&amp;&amp;,gcc 将是A const&amp;.foo(),clang 将是A const&amp;&amp;.foo(),VS 将是A const&amp;&amp;.foo(),并调用了一个复制ctor。

clang 是正确的吗?谢谢!

【问题讨论】:

标签: c++ c++11 c++14 c++17 value-categories


【解决方案1】:

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

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

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

最新的 MSVC 也打印正确的输出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-02
    • 2021-08-01
    • 2016-04-13
    • 2016-07-02
    • 1970-01-01
    • 1970-01-01
    • 2018-01-02
    • 1970-01-01
    相关资源
    最近更新 更多