It is not specified where exactly in its storage std::optional
stores the object. If you assume that the location of the object is always the same for the same type T
, 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 the T
object. You would need to std::launder
the resulting pointer to make it usable, which will only be allowed if sizeof(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 for std::launder
, see https://en.cppreference.com/w/cpp/utility/launder)
Whether or not the use of the reinterpret_cast
and 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 union
of a std::optional<T>
with a unsigned 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 the T
value. See e.g this answer.