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
- Is it ok to ignore
std::launder
? I guess not. - Since
std::launder
is available only in c++17, how to implement above class in c++14?boost::optional
andstd::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
No, you can't. One of the reasons that
std::launder
is proposed is thatstd::optional
is not implementable in C++14. You can refer to this discussion for detail.On the other hand, you can implement one without
constexpr
. The idea is to use a buffer withreinterpret_cast
because the result ofreinterpret_cast
will always refer to the newly created object (in C++17std::launder
is still required but in C++14 this is fine). For example,The implementation of
boost::optional
uses this idea and does not implementconstexpr
semantic (you can refer to its source code for details).