Support non-trivial Optional values (#1106)
Commit
7224761 skipped this std::optional feature when adding initial
Optional implementation because that feature is difficult to support.
However, several in-progress projects now need to make non-trivial
objects Optional. This implementation maintains key Optional invariants,
matching those of std::optional:
* A valueless Optional object does not construct or destruct the value.
* A valued Optional object supports move/copy ops supported by value.
Maintaining the first invariant is tricky:
* Union prevents value construction/destruction in a valueless Optional.
* Explicit destructor call destructs the value in a _valued_ Optional.
* A dummy union member works around a C++ requirement for constexpr
unions to have at least one active (i.e. initialized) member. Since a
valueless Optional cannot initialize the value, we need another union
member that we can initialize.
* We use an _anonymous_ union because C++ places more requirements on
named unions, triggering a more complex implementation with
placement-new and to-be-deprecated std::aligned_storage_t tricks!
XXX: This simplified implementation violates the following std::optional
invariant. We believe that this violation does not hurt the current and
foreseeable Squid code. In our tests, optimizing compilers still
optimize Optional<Trivial> destructors away.
* std::optional<Value> is trivially destructible if Value is.