It is like std::optional
, but doesn't store an extra bool. User has to make sure to access only after initializing.
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;
};
If you are wondering why I need such an obscure datastructure, check here: https://gitlab.com/balki/linkedlist/tree/master
Question
std::launder
? I guess not.std::launder
is available only in c++17, how to implement above class in c++14? boost::optional
and std::experimental::optional
should have needed similar feature or did they use compiler specific magic?Note: It is easy to miss, the type is declared as union
. Which means constructor of T
is really not called. Ref: https://gcc.godbolt.org/z/EVpfSN
答案 0 :(得分:3)
不,您不能。提出std::launder
的原因之一是std::optional
在C ++ 14中无法实现。您可以参考this discussion了解详情。
另一方面,您可以不使用constexpr
来实现。想法是将缓冲区与reinterpret_cast
一起使用,因为reinterpret_cast
的结果将始终引用新创建的对象(在C ++ 17中仍然需要std::launder
,但在C ++ 14中这可以)。例如,
template<class T>
struct FakeOptional {
FakeOptional(){}
template<class... Args>
void emplace(Args&&... args){
new(&storage) T{std::forward<Args&&>(args)...};
}
void reset(){
reinterpret_cast<T*>(&storage)->~T();
}
operator bool() const {
return true;
}
const T* operator->() const {
return reinterpret_cast<const T*>(&storage);
}
T* operator->() {
return reinterpret_cast<T*>(&storage);
}
std::aligned_storage_t<sizeof(T), alignof(T)> storage;
};
boost::optional
uses this idea的实现,并且没有实现constexpr
语义(有关详细信息,您可以参考其source code)。