【发布时间】:2019-06-13 01:37:22
【问题描述】:
类似于std::optional,但不存储额外的布尔值。用户必须确保只有在初始化后才能访问。
template<class T>
union FakeOptional { //Could be a normal struct in which case will need std::aligned storage object.
FakeOptional(){} //Does not construct T
template<class... Args>
void emplace(Args&&... args){
new(&t) T{std::forward<Args&&>(args)...};
}
void reset(){
t.~T();
}
operator bool() const {
return true;
}
constexpr const T* operator->() const {
return std::launder(&t);
}
constexpr T* operator->() {
return std::launder(&t);
}
T t;
};
如果您想知道为什么我需要这样一个晦涩难懂的数据结构,请在此处查看:https://gitlab.com/balki/linkedlist/tree/master
问题
- 可以忽略
std::launder吗?我猜不是。 - 既然
std::launder只在c++17中可用,那么如何在c++14中实现上面的类呢?boost::optional和std::experimental::optional应该需要类似的功能,还是他们使用了特定于编译器的魔法?
注意:很容易漏掉,类型声明为union。这意味着 T 的构造函数实际上没有被调用。参考:https://gcc.godbolt.org/z/EVpfSN
【问题讨论】:
-
只需将 new 放入字节数组 +
reinterpret_cast即可。 -
operator bool() const { return true; }...FakeOptional。是的,听起来不错。 -
@FrançoisAndrieux 这是一个联合,而不是结构。所以它没有被构造。这就是这种类型的全部要点。避免默认构造,但只分配足够的,以后可以使用。
-
@NicolBolas,我正在使用联合。注意:
union FakeOptional -
它完全是编译器的构造,你必须有编译器支持。你能做的最好的就是检查是否有
__builtin_launder或类似的东西。
标签: c++ c++14 language-lawyer c++17 stdlaunder