clang 20.0.0git
CustomizableOptional.h
Go to the documentation of this file.
1//===- CustomizableOptional.h - Optional with custom storage ----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef CLANG_BASIC_CUSTOMIZABLEOPTIONAL_H
10#define CLANG_BASIC_CUSTOMIZABLEOPTIONAL_H
11
12#include "llvm/ADT/Hashing.h"
13#include "llvm/Support/Compiler.h"
14#include "llvm/Support/type_traits.h"
15#include <cassert>
16#include <new>
17#include <optional>
18#include <utility>
19
20namespace clang {
21
22namespace optional_detail {
23template <typename> class OptionalStorage;
24} // namespace optional_detail
25
26// Optional type which internal storage can be specialized by providing
27// OptionalStorage. The interface follows std::optional.
28template <typename T> class CustomizableOptional {
30
31public:
32 using value_type = T;
33
34 constexpr CustomizableOptional() = default;
35 constexpr CustomizableOptional(std::nullopt_t) {}
36
37 constexpr CustomizableOptional(const T &y) : Storage(std::in_place, y) {}
38 constexpr CustomizableOptional(const CustomizableOptional &O) = default;
39
40 constexpr CustomizableOptional(T &&y)
41 : Storage(std::in_place, std::move(y)) {}
43
44 template <typename... ArgTypes>
45 constexpr CustomizableOptional(std::in_place_t, ArgTypes &&...Args)
46 : Storage(std::in_place, std::forward<ArgTypes>(Args)...) {}
47
48 // Allow conversion from std::optional<T>.
49 constexpr CustomizableOptional(const std::optional<T> &y)
51 constexpr CustomizableOptional(std::optional<T> &&y)
52 : CustomizableOptional(y ? std::move(*y) : CustomizableOptional()) {}
53
55 Storage = std::move(y);
56 return *this;
57 }
59
60 /// Create a new object by constructing it in place with the given arguments.
61 template <typename... ArgTypes> void emplace(ArgTypes &&...Args) {
62 Storage.emplace(std::forward<ArgTypes>(Args)...);
63 }
64
66 Storage = y;
67 return *this;
68 }
70
71 void reset() { Storage.reset(); }
72
73 LLVM_DEPRECATED("Use &*X instead.", "&*X")
74 constexpr const T *getPointer() const { return &Storage.value(); }
75 LLVM_DEPRECATED("Use &*X instead.", "&*X")
76 T *getPointer() { return &Storage.value(); }
77 LLVM_DEPRECATED("std::optional::value is throwing. Use *X instead", "*X")
78 constexpr const T &value() const & { return Storage.value(); }
79 LLVM_DEPRECATED("std::optional::value is throwing. Use *X instead", "*X")
80 T &value() & { return Storage.value(); }
81
82 constexpr explicit operator bool() const { return has_value(); }
83 constexpr bool has_value() const { return Storage.has_value(); }
84 constexpr const T *operator->() const { return &Storage.value(); }
85 T *operator->() { return &Storage.value(); }
86 constexpr const T &operator*() const & { return Storage.value(); }
87 T &operator*() & { return Storage.value(); }
88
89 template <typename U> constexpr T value_or(U &&alt) const & {
90 return has_value() ? operator*() : std::forward<U>(alt);
91 }
92
93 LLVM_DEPRECATED("std::optional::value is throwing. Use *X instead", "*X")
94 T &&value() && { return std::move(Storage.value()); }
95 T &&operator*() && { return std::move(Storage.value()); }
96
97 template <typename U>