The rules surrounding constexpr for std::optional seem inconsistent -- like there are a lot of functions that are "just" missing the keyword due to oversight.
For example, `optional(std::nullopt_t)` is constexpr, but `optional &operator=(std::nullopt_t)` is not.
// Okay
```
constexpr std::optional<int> ValidOptional = []{
std::optional<int> opt(std::nullopt);
opt = std::optional<int>(std::nullopt);
return opt;
}();
```
// Compiler error
```
constexpr std::optional<int> InvalidOptional = []{
std::optional<int> opt(std::nullopt);
opt = std::nullopt;
return opt;
}();
```
Other oversights:
`template<typename U> optional(U &&)` is constexpr, but `template<typename U> optional &operator=(U &&)` is not.
Things that are less obviously oversights, but might want to change:
`emplace` is not constexpr, even though the constructors it would call are.
`reset` is not constexpr.
`swap(optional &)` is not constexpr, nor is std::swap for optionals. (std::swap is constexpr for other types).
copy constructor/move constructor for template<typename T> optional<U> are not constexpr, even though optional(U &&) is.
If the following changed, copy/move assignment operators would probably also want to be constexpr.
--