Given a std::optional<T> is it possible to derive the address of the std::optional<T> from the address of the T?
possible implementation:
template<typename T>
struct myoptional
{ static std::size_t getOffset(void)
{ static const myoptional<T> s(std::inplace());
return reinterpret_cast<const char*>(&s.value())
- reinterpret_cast<const char*>(&s);
};
};
It is not specified where exactly in its storage
std::optionalstores the object. If you assume that the location of the object is always the same for the same typeT, you can maybe (see below) use the shown method to obtain an offset through the object representation.However, even if you knew the offset of the object, you would still not be able to obtain a usable pointer to the
std::optional<T>from a pointer to theTobject. You would need tostd::launderthe resulting pointer to make it usable, which will only be allowed ifsizeof(std::optional<T>) <= sizeof(T), which seems unlikely/impossible. (Otherwise it would make previously unreachable bytes reachable in the meaning of the term reachable as in the preconditions forstd::launder, see https://en.cppreference.com/w/cpp/utility/launder)Whether or not the use of the
reinterpret_castand the pointer arithmetic is allowed by the standard is not clear at the moment. The standard has some unresolved defects in that regard.What you can do alternatively though and (as far as I can tell) shouldn't have undefined behavior is to use a
unionof astd::optional<T>with aunsigned char[sizeof(std::optional<T>)]and instead of using a pointer difference, you can then use addition and pointer comparison in a loop to find the offset in the character array matching the address of theTvalue. See e.g this answer.