operator T&&() && {
valid_ = false;
return std::move(value());
}
你的问题在于
valid_ = false;
这一行是错误的。
你的类有一个不变量,即它要么包含一个值且
valid_
为
true
,要么不包含值且
valid_
为
false
。
你的
operator T&&()&&
违反了这个不变量。
可选方案包括:
operator T&&() && {
return std::move(value());
}
或者
operator T() && {
T tmp = std::move(value());
value().~T();
valid_ = false;
return tmp;
}
std::optional
使用第一个,第二个也是可能的。
顺带一提:
maybe(T value) : valid_(true) { new (&value_) T(value); }
需要使用
std::move
:
maybe(T value) : valid_(true) { new (&value_) T(std::move(value)); }
和其他防御措施:
maybe(T value) : valid_(true) { ::new ((void*)&value_) T(std::move(value)); }
需要处理operator new
重载。
接下来,你需要处理抛出异常的构造函数:
maybe(T value) : maybe() {
::new ((void*)&value_) T(std::move(value));
valid_ = true;
}
你应该更进一步。
template<class...Args>
void emplace(Args&&...args) {
if (*this)
clear();
::new( (void*)&value_ ) T( std::forward<Args>(args)... );
valid_ = true;
}
void clear() {
if (*this)
{
valid_ = false;
value().~T();
}
}
现在我们:
maybe(T value)
: maybe() {
emplace( std::move(value ) );
}
~maybe()
{
clear();
}
只需手动调整emplace()
和clear()
中的value_
和valid_
生命周期。
我们还应该拥有有效的noexcept
值:
template<class...Args>
void emplace(Args&&...args)
noexcept(
noexcept( T( std::forward<Args>(args)... )
&& noexcept( std::declval<maybe&>().clear() )
)
{
if (*this)
clear();
::new( (void*)&value_ ) T( std::forward<Args>(args)... );
valid_ = true;
}
void clear() noexcept(noexcept( std::declval<T&>().~T() ) ) {
if (*this)
{
valid_ = false;
value().~T();
}
}
现在我们:
maybe(T value)
noexcept( noexcept( std::declval<maybe&>().emplace( std::declval<T&&>() ) ) )
: maybe() {
emplace( std::move(value ) );
}
~maybe()
noexcept( noexcept( std::declval<maybe&>().clear() ) )
{
clear();
}