【发布时间】: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&.foo()
叮当声:A&&.foo()
对比:
A move ctor
A&&.foo()
如果我们将两种操作数类型都转换为A const&&,gcc 将是A const&.foo(),clang 将是A const&&.foo(),VS 将是A const&&.foo(),并调用了一个复制ctor。
clang 是正确的吗?谢谢!
【问题讨论】:
-
结果是一个
A类型的xvalue;输出应与std::move(a).foo();相同 -
根据this answer应该是
A&&.foo() -
是的,clang 是正确的。 MSVC 制作副本是错误的。我为 gcc 发布了一个错误报告:gcc.gnu.org/bugzilla/show_bug.cgi?id=88103
-
有点相关question here 哪里 gcc 也得到它不正确。
标签: c++ c++11 c++14 c++17 value-categories