It seems to me that `optional` is not usable in compile-time before C++20, because switching union active member is not allowed, and so it doesn't make sense to mark `optional()` as constexpr, but maybe I have missed something.
That's a good point. Interestingly enough, the following code happened to work on both gcc and clang with C++17:
constexpr void foo() {
std::optional<int> opt;
opt = 2;
}
yet it's clear that there is an "invocation of an assignment operator that would change the active member of a union" (removed in p1330) in both libstdc++ and libc++.
why in your initial example `dummy` is an array? If it's a single object, pessimization due to zero-initialization will be reduced
Another reason (a bit technical and implementation specific) was that having union members of different sizes were optimized by clang/llvm by storing shared and non-shared parts of the union in separate memory locations, which caused conservative garbage collection used in the Chrome's renderer to miss the pointer stored in an optional.
If it's a single object, pessimization due to zero-initialization will be reduced
Having zero-initialization even for a single empty object is already pessimization. We're just lucky that for a single object it gets optimized away by clang, but at the same time are unlucky that for the whole array it doesn't (as opposed to gcc).
It would be very strange if for the `pair<int, array<int, 1>> p;` p.first == 0, but p.second[0] has indeterminate value.
The example totally makes sense, thanks.
I think that technically even for a single empty object its 'value' may be observable (e.g. through char* aliasing), but I don't think there is a real use case for this, given that compilers already optimize such cases. I wonder if it would make sense to expand the definition of empty class from type traits to the Core to allow for more optimizations.