For the case where rhs.has_value() is false and
this->has_value() is true, equivalent to:
if constexpr (is_nothrow_move_constructible_v<E>) {
  E tmp(std::move(rhs.unex));
  destroy_at(addressof(rhs.unex));
  try {
    construct_at(addressof(rhs.val), std::move(val));
    destroy_at(addressof(val));
    construct_at(addressof(unex), std::move(tmp));
  } catch(...) {
    construct_at(addressof(rhs.unex), std::move(tmp));
    throw;
  }
} else {
  T tmp(std::move(val));
  destroy_at(addressof(val));
  try {
    construct_at(addressof(unex), std::move(rhs.unex));
    destroy_at(addressof(rhs.unex));
    construct_at(addressof(rhs.val), std::move(tmp));
  } catch (...) {
    construct_at(addressof(val), std::move(tmp));
    throw;
  }
}
has_val = false;
rhs.has_val = true;