//===- OptionalEnum.h - Space-efficient variant for enum values -*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://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(llvm::NoneType) : 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(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; } }; } #endif