mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
LLVM has removed llvm::Optional, move over to std::optional. Also clang-format to fix up all the renamed #includes.
115 lines
3.6 KiB
C++
115 lines
3.6 KiB
C++
//===- OptionalEnum.h - Space-efficient variant for enum values -*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_BASIC_OPTIONALENUM_H
|
|
#define SWIFT_BASIC_OPTIONALENUM_H
|
|
|
|
#include "swift/Basic/type_traits.h"
|
|
#include <type_traits>
|
|
|
|
namespace swift {
|
|
template<typename T>
|
|
class OptionalEnum {
|
|
using underlying_type = typename std::underlying_type<T>::type;
|
|
static_assert(IsTriviallyCopyable<T>::value, "type is not trivial");
|
|
static_assert(std::is_integral<underlying_type>::value,
|
|
"underlying type is not integral");
|
|
public:
|
|
using value_type = T;
|
|
using storage_type = typename std::make_unsigned<underlying_type>::type;
|
|
|
|
private:
|
|
storage_type Storage;
|
|
|
|
public:
|
|
/// Construct an empty instance.
|
|
OptionalEnum() : Storage(0) { }
|
|
|
|
/// Construct an empty instance.
|
|
/*implicit*/ OptionalEnum(std::nullopt_t) : OptionalEnum() {}
|
|
|
|
/// Construct an instance containing a value of type \c T constructed with
|
|
/// the given argument.
|
|
template<typename U>
|
|
/*implicit*/ OptionalEnum(
|
|
U &&value,
|
|
typename std::enable_if<std::is_convertible<U, T>::value>::type * = {})
|
|
: Storage(static_cast<storage_type>(T{std::forward<U>(value)}) + 1) {
|
|
assert(hasValue() && "cannot store this value");
|
|
}
|
|
|
|
/// Construct the enum from its raw integral representation.
|
|
///
|
|
/// This can be used to interoperate with PointerIntPair.
|
|
template<typename I>
|
|
explicit OptionalEnum(
|
|
I rawValue,
|
|
typename std::enable_if<std::is_integral<I>::value>::type * = {})
|
|
: Storage(rawValue) {
|
|
assert((uintptr_t)rawValue == (uintptr_t)(intptr_t)*this);
|
|
}
|
|
|
|
void reset() {
|
|
Storage = 0;
|
|
}
|
|
|
|
bool hasValue() const { return Storage != 0; }
|
|
explicit operator bool() const { return hasValue(); }
|
|
|
|
T getValue() const {
|
|
assert(hasValue());
|
|
return static_cast<value_type>(Storage - 1);
|
|
}
|
|
T operator*() { return getValue(); }
|
|
|
|
template <typename U>
|
|
constexpr T getValueOr(U &&value) const {
|
|
return hasValue() ? getValue() : value;
|
|
}
|
|
|
|
/// Converts the enum to its raw storage value, for interoperation with
|
|
/// PointerIntPair.
|
|
explicit operator intptr_t() const {
|
|
assert(Storage == (storage_type)(intptr_t)Storage);
|
|
return (intptr_t)Storage;
|
|
}
|
|
|
|
// Provide comparison operators for the optional value.
|
|
|
|
friend bool operator==(const OptionalEnum &lhs, const OptionalEnum &rhs) {
|
|
return (!lhs && !rhs) || (lhs && rhs && lhs.getValue() == rhs.getValue());
|
|
}
|
|
|
|
friend bool operator!=(const OptionalEnum &lhs, const OptionalEnum &rhs) {
|
|
return !(lhs == rhs);
|
|
}
|
|
|
|
friend bool operator<(const OptionalEnum &lhs, const OptionalEnum &rhs) {
|
|
return rhs && (!lhs || lhs.getValue() < rhs.getValue());
|
|
}
|
|
|
|
friend bool operator>(const OptionalEnum &lhs, const OptionalEnum &rhs) {
|
|
return rhs < lhs;
|
|
}
|
|
|
|
friend bool operator<=(const OptionalEnum &lhs, const OptionalEnum &rhs) {
|
|
return !(rhs < lhs);
|
|
}
|
|
|
|
friend bool operator>=(const OptionalEnum &lhs, const OptionalEnum &rhs) {
|
|
return !(lhs < rhs);
|
|
}
|
|
};
|
|
} // end namespace swift
|
|
|
|
#endif // SWIFT_BASIC_OPTIONALENUM_H
|