In real code, constructors can be very complex and so the emplace
of a std::optional
can query the status of the optional itself. When this happens it's usually a bit more convoluted, but here is a (contrived) minimal example:
#include <iostream>
#include <optional>
struct Thing {
Thing();
};
std::optional<Thing> othing;
Thing::Thing() {
std::cout << othing.has_value() << std::endl;
}
int main() {
othing.emplace();
}
For all three major standard library implementations, this yields false
. In other words during the execution of the emplacing constructor, the optional does not contain a value.
From an implementation perspective, this means that the value is constructed in-place first and afterwards some bookkeeping variable is set. And this is indeed the case in MSVC, libc++ and libstdc++.
Now the relevant part of the standard reads
[...] When an instance of
optional<T>
contains a value, it means that an object of type T, referred to as the optional object's contained value, is allocated within the storage of the optional object.
Interestingly this doesn't use the clearly defined lifetime of the contained object (I suppose because this can be forcibly be ended from outside, e.g. othing->~Thing()
), but the term allocated within the storage. The standard usually speaks of allocation in the context of dynamic memory and in these cases, allocation clearly takes place before construction.
So I would argue that the mentioned standard library implementations are not compliant, the bookkeeping variable should be set right before construction starts.
Under this assumption one question remains: Are the implementations better than the standard and isn't it rather the latter that needs to be fixed or clarified? I don't think so: During construction of large objects it's perfectly valid and common to access already initialized subobjects, so this should be possible for objects contained in an optional as well.
So are my considerations right? Or is my interpretation of the term allocated within incorrect? And are there arguments against my standpoint of what's the RightThing™ to do?