C++ 您是否可以从std::optional<;T>;其中T有非平凡构造函数?
我试图用叮当声编译WebKit,我之所以这么做,主要是因为以下模式:C++ 您是否可以从std::optional<;T>;其中T有非平凡构造函数?,c++,webkit,c++17,optional,C++,Webkit,C++17,Optional,我试图用叮当声编译WebKit,我之所以这么做,主要是因为以下模式: #include <iostream> #include <optional> struct X { X() = default; X(const X& other) { } }; struct Y { std::optional<X> x;; }; int main() { Y foo; Y bar(std::move(foo)); }
#include <iostream>
#include <optional>
struct X {
X() = default;
X(const X& other) { }
};
struct Y {
std::optional<X> x;;
};
int main() {
Y foo;
Y bar(std::move(foo));
}
这是有效的C++,还是WebKIT损坏,CLAN合法拒绝这个代码?
< P>考虑这个类:struct X
{
X(int);
X(X&&) = delete;
// does this need to invoke the move constructor??
X() : X(X(0)) { }
};
根据gcc,答案是否定的:这将直接委托给X(int)
。根据clang的说法,答案是肯定的,但编译失败:
此类型已隐式删除了复制和移动构造函数,这是因为具有不可复制构造的成员的联合。因此,如果这个委托构造函数必须调用隐式复制构造函数(如clang所认为的),那么这是格式错误的。如果不必这样做,只需调用一个或另一个委托构造函数,那么这个调用就可以了
Y{}
已经是临时的,所以std::move
是多余的。@Jarod42我想OP使用它是为了避免复制省略。@Jarod42经过编辑,只是为了让示例更清楚一点。我在godbolt.org上试用过,在我测试过的所有编译器(最新的MSVC、gcc和clang)中都编译得很好。不确定它使用的是什么libstdc++版本(也适用于libc++),所以它可能是8.1.1(或在clang&8.1.1组合中)中的一些“bug”。@Dan hm ok我尝试了clanghead和clang6.0.1与7.3.1和8.1.1的GCC库。我想我还需要设置一个Ubuntu在那里进行测试。所以根据这个(很棒!)的分析,在WebKit中以这种特殊的方式使用std::optional应该被认为是一个bug,或者在libstdc++中实现std::optional应该被认为是一个bug?在任何一种情况下,我都将通过降级到旧版本的libstdc++来解决这个问题,但我可能会让WebKit开发人员知道是否是前者。最近在core reflector上讨论了这个确切的示例—请参阅标题为“强制副本省略与ctor委派”的线程。
struct X
{
X(int);
X(X&&) = delete;
// does this need to invoke the move constructor??
X() : X(X(0)) { }
};
<source>:55:15: error: call to deleted constructor of 'X'
X() : X(X(0)) { }
^ ~~~~
<source>:52:9: note: 'X' has been explicitly marked deleted here
X(X&&) = delete;
^
constexpr
_Optional_payload(bool __engaged, _Optional_payload&& __other)
: _Optional_payload(__engaged
? _Optional_payload(__ctor_tag<bool>{},
std::move(__other._M_payload))
: _Optional_payload(__ctor_tag<void>{}))
{ }