//===- 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 namespace swift { template class OptionalEnum { using underlying_type = typename std::underlying_type::type; static_assert(IsTriviallyCopyable::value, "type is not trivial"); static_assert(std::is_integral::value, "underlying type is not integral"); public: using value_type = T; using storage_type = typename std::make_unsigned::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 /*implicit*/ OptionalEnum( U &&value, typename std::enable_if::value>::type * = {}) : Storage(static_cast(T{std::forward(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 explicit OptionalEnum( I rawValue, typename std::enable_if::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(Storage - 1); } T operator*() { return getValue(); } template 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