Some types have a representation that would allow them to serve as their own
optional. For example PythonObject in LLDB is just a PyObject * under
the hood. An Optional<PythonObject> could be represented by that one pointer,
with the value of NULL in the None case.
Right now, instead of using Optional<PythonObject>, we just allow them to be in
an invalid state, with lots of checks to PythonObject::IsValid everywhere.
I think it would be better to actually mark which PythonObjects are allowed
to be invalid using optionals. But it seems like a shame to add an extra runtime
bool when we can just use a NULL pointer instead.
I'm posting this patch as a straw-man, as I strongly suspect there's a better way
to do it.
It creates a type trait llvm::optional_detail::has_is_valid. If a class
is marked with this trait, it should implement MakeInvalid() and IsValid().
What I like: it's easy to opt a class in without a bunch of boilerplate.
What I don't like: MakeInvalid() isn't private, even though you're not supposed to,
you can still create invalid objects instead of using optionals.
Another way to do it would be to require the invalid state is all zeros represent
it as
union { T value; uint8_t bytes[sizeof(T)]; }
What do you think? Is this a good idea in general? If so, what's the right way
to implement it?
Also who else should be added to reviewers?
Slight note (borrowed from this thread.
This implementation, compared to the generic one, is not type-safe and relies on an assert on y to check whether it's the sentinel or not. This is a slight change that may matter (somehow trading type-safety for performance).
Possible exploration path: if the sentinel has its own type (e.g. std::nullptr_t) we somehow improve type safety, but still don't have the same guarantee as the generic implementation.