Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:48

0001 //===- CustomizableOptional.h - Optional with custom storage ----*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef CLANG_BASIC_CUSTOMIZABLEOPTIONAL_H
0010 #define CLANG_BASIC_CUSTOMIZABLEOPTIONAL_H
0011 
0012 #include "llvm/ADT/Hashing.h"
0013 #include "llvm/Support/Compiler.h"
0014 #include "llvm/Support/type_traits.h"
0015 #include <cassert>
0016 #include <new>
0017 #include <optional>
0018 #include <utility>
0019 
0020 namespace clang {
0021 
0022 namespace optional_detail {
0023 template <typename> class OptionalStorage;
0024 } // namespace optional_detail
0025 
0026 // Optional type which internal storage can be specialized by providing
0027 // OptionalStorage. The interface follows std::optional.
0028 template <typename T> class CustomizableOptional {
0029   optional_detail::OptionalStorage<T> Storage;
0030 
0031 public:
0032   using value_type = T;
0033 
0034   constexpr CustomizableOptional() = default;
0035   constexpr CustomizableOptional(std::nullopt_t) {}
0036 
0037   constexpr CustomizableOptional(const T &y) : Storage(std::in_place, y) {}
0038   constexpr CustomizableOptional(const CustomizableOptional &O) = default;
0039 
0040   constexpr CustomizableOptional(T &&y)
0041       : Storage(std::in_place, std::move(y)) {}
0042   constexpr CustomizableOptional(CustomizableOptional &&O) = default;
0043 
0044   template <typename... ArgTypes>
0045   constexpr CustomizableOptional(std::in_place_t, ArgTypes &&...Args)
0046       : Storage(std::in_place, std::forward<ArgTypes>(Args)...) {}
0047 
0048   // Allow conversion from std::optional<T>.
0049   constexpr CustomizableOptional(const std::optional<T> &y)
0050       : CustomizableOptional(y ? *y : CustomizableOptional()) {}
0051   constexpr CustomizableOptional(std::optional<T> &&y)
0052       : CustomizableOptional(y ? std::move(*y) : CustomizableOptional()) {}
0053 
0054   CustomizableOptional &operator=(T &&y) {
0055     Storage = std::move(y);
0056     return *this;
0057   }
0058   CustomizableOptional &operator=(CustomizableOptional &&O) = default;
0059 
0060   /// Create a new object by constructing it in place with the given arguments.
0061   template <typename... ArgTypes> void emplace(ArgTypes &&...Args) {
0062     Storage.emplace(std::forward<ArgTypes>(Args)...);
0063   }
0064 
0065   CustomizableOptional &operator=(const T &y) {
0066     Storage = y;
0067     return *this;
0068   }
0069   CustomizableOptional &operator=(const CustomizableOptional &O) = default;
0070 
0071   void reset() { Storage.reset(); }
0072 
0073   LLVM_DEPRECATED("Use &*X instead.", "&*X")
0074   constexpr const T *getPointer() const { return &Storage.value(); }
0075   LLVM_DEPRECATED("Use &*X instead.", "&*X")
0076   T *getPointer() { return &Storage.value(); }
0077   LLVM_DEPRECATED("std::optional::value is throwing. Use *X instead", "*X")
0078   constexpr const T &value() const & { return Storage.value(); }
0079   LLVM_DEPRECATED("std::optional::value is throwing. Use *X instead", "*X")
0080   T &value() & { return Storage.value(); }
0081 
0082   constexpr explicit operator bool() const { return has_value(); }
0083   constexpr bool has_value() const { return Storage.has_value(); }
0084   constexpr const T *operator->() const { return &Storage.value(); }
0085   T *operator->() { return &Storage.value(); }
0086   constexpr const T &operator*() const & { return Storage.value(); }
0087   T &operator*() & { return Storage.value(); }
0088 
0089   template <typename U> constexpr T value_or(U &&alt) const & {
0090     return has_value() ? operator*() : std::forward<U>(alt);
0091   }
0092 
0093   LLVM_DEPRECATED("std::optional::value is throwing. Use *X instead", "*X")
0094   T &&value() && { return std::move(Storage.value()); }
0095   T &&operator*() && { return std::move(Storage.value()); }
0096 
0097   template <typename U> T value_or(U &&alt) && {
0098     return has_value() ? std::move(operator*()) : std::forward<U>(alt);
0099   }
0100 };
0101 
0102 template <typename T>
0103 CustomizableOptional(const T &) -> CustomizableOptional<T>;
0104 
0105 template <class T>
0106 llvm::hash_code hash_value(const CustomizableOptional<T> &O) {
0107   return O ? llvm::hash_combine(true, *O) : llvm::hash_value(false);
0108 }
0109 
0110 template <typename T, typename U>
0111 constexpr bool operator==(const CustomizableOptional<T> &X,
0112                           const CustomizableOptional<U> &Y) {
0113   if (X && Y)
0114     return *X == *Y;
0115   return X.has_value() == Y.has_value();
0116 }
0117 
0118 template <typename T, typename U>
0119 constexpr bool operator!=(const CustomizableOptional<T> &X,
0120                           const CustomizableOptional<U> &Y) {
0121   return !(X == Y);
0122 }
0123 
0124 template <typename T, typename U>
0125 constexpr bool operator<(const CustomizableOptional<T> &X,
0126                          const CustomizableOptional<U> &Y) {
0127   if (X && Y)
0128     return *X < *Y;
0129   return X.has_value() < Y.has_value();
0130 }
0131 
0132 template <typename T, typename U>
0133 constexpr bool operator<=(const CustomizableOptional<T> &X,
0134                           const CustomizableOptional<U> &Y) {
0135   return !(Y < X);
0136 }
0137 
0138 template <typename T, typename U>
0139 constexpr bool operator>(const CustomizableOptional<T> &X,
0140                          const CustomizableOptional<U> &Y) {
0141   return Y < X;
0142 }
0143 
0144 template <typename T, typename U>
0145 constexpr bool operator>=(const CustomizableOptional<T> &X,
0146                           const CustomizableOptional<U> &Y) {
0147   return !(X < Y);
0148 }
0149 
0150 template <typename T>
0151 constexpr bool operator==(const CustomizableOptional<T> &X, std::nullopt_t) {
0152   return !X;
0153 }
0154 
0155 template <typename T>
0156 constexpr bool operator==(std::nullopt_t, const CustomizableOptional<T> &X) {
0157   return X == std::nullopt;
0158 }
0159 
0160 template <typename T>
0161 constexpr bool operator!=(const CustomizableOptional<T> &X, std::nullopt_t) {
0162   return !(X == std::nullopt);
0163 }
0164 
0165 template <typename T>
0166 constexpr bool operator!=(std::nullopt_t, const CustomizableOptional<T> &X) {
0167   return X != std::nullopt;
0168 }
0169 
0170 template <typename T>
0171 constexpr bool operator<(const CustomizableOptional<T> &, std::nullopt_t) {
0172   return false;
0173 }
0174 
0175 template <typename T>
0176 constexpr bool operator<(std::nullopt_t, const CustomizableOptional<T> &X) {
0177   return X.has_value();
0178 }
0179 
0180 template <typename T>
0181 constexpr bool operator<=(const CustomizableOptional<T> &X, std::nullopt_t) {
0182   return !(std::nullopt < X);
0183 }
0184 
0185 template <typename T>
0186 constexpr bool operator<=(std::nullopt_t, const CustomizableOptional<T> &X) {
0187   return !(X < std::nullopt);
0188 }
0189 
0190 template <typename T>
0191 constexpr bool operator>(const CustomizableOptional<T> &X, std::nullopt_t) {
0192   return std::nullopt < X;
0193 }
0194 
0195 template <typename T>
0196 constexpr bool operator>(std::nullopt_t, const CustomizableOptional<T> &X) {
0197   return X < std::nullopt;
0198 }
0199 
0200 template <typename T>
0201 constexpr bool operator>=(const CustomizableOptional<T> &X, std::nullopt_t) {
0202   return std::nullopt <= X;
0203 }
0204 
0205 template <typename T>
0206 constexpr bool operator>=(std::nullopt_t, const CustomizableOptional<T> &X) {
0207   return X <= std::nullopt;
0208 }
0209 
0210 template <typename T>
0211 constexpr bool operator==(const CustomizableOptional<T> &X, const T &Y) {
0212   return X && *X == Y;
0213 }
0214 
0215 template <typename T>
0216 constexpr bool operator==(const T &X, const CustomizableOptional<T> &Y) {
0217   return Y && X == *Y;
0218 }
0219 
0220 template <typename T>
0221 constexpr bool operator!=(const CustomizableOptional<T> &X, const T &Y) {
0222   return !(X == Y);
0223 }
0224 
0225 template <typename T>
0226 constexpr bool operator!=(const T &X, const CustomizableOptional<T> &Y) {
0227   return !(X == Y);
0228 }
0229 
0230 template <typename T>
0231 constexpr bool operator<(const CustomizableOptional<T> &X, const T &Y) {
0232   return !X || *X < Y;
0233 }
0234 
0235 template <typename T>
0236 constexpr bool operator<(const T &X, const CustomizableOptional<T> &Y) {
0237   return Y && X < *Y;
0238 }
0239 
0240 template <typename T>
0241 constexpr bool operator<=(const CustomizableOptional<T> &X, const T &Y) {
0242   return !(Y < X);
0243 }
0244 
0245 template <typename T>
0246 constexpr bool operator<=(const T &X, const CustomizableOptional<T> &Y) {
0247   return !(Y < X);
0248 }
0249 
0250 template <typename T>
0251 constexpr bool operator>(const CustomizableOptional<T> &X, const T &Y) {
0252   return Y < X;
0253 }
0254 
0255 template <typename T>
0256 constexpr bool operator>(const T &X, const CustomizableOptional<T> &Y) {
0257   return Y < X;
0258 }
0259 
0260 template <typename T>
0261 constexpr bool operator>=(const CustomizableOptional<T> &X, const T &Y) {
0262   return !(X < Y);
0263 }
0264 
0265 template <typename T>
0266 constexpr bool operator>=(const T &X, const CustomizableOptional<T> &Y) {
0267   return !(X < Y);
0268 }
0269 
0270 } // namespace clang
0271 
0272 #endif // CLANG_BASIC_CUSTOMIZABLEOPTIONAL_H