[libc][NFC] Move aligned access implementations to separate header
[llvm-project.git] / libc / src / __support / CPP / optional.h
blob8b3959514108d4fa89190461f99cba15cbde21eb
1 //===-- Standalone implementation of std::optional --------------*- 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 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIBC_SRC_SUPPORT_CPP_OPTIONAL_H
10 #define LLVM_LIBC_SRC_SUPPORT_CPP_OPTIONAL_H
12 #include "src/__support/CPP/type_traits.h"
13 #include "src/__support/CPP/utility.h"
14 #include "src/__support/macros/attributes.h"
16 namespace __llvm_libc {
17 namespace cpp {
19 // Trivial in_place_t struct.
20 struct in_place_t {
21 LIBC_INLINE_VAR explicit in_place_t() = default;
24 // Trivial nullopt_t struct.
25 struct nullopt_t {
26 LIBC_INLINE_VAR explicit nullopt_t() = default;
29 // nullopt that can be used and returned.
30 LIBC_INLINE_VAR constexpr nullopt_t nullopt{};
32 // in_place that can be used in the constructor.
33 LIBC_INLINE_VAR constexpr in_place_t in_place{};
35 // This is very simple implementation of the std::optional class. It makes
36 // several assumptions that the underlying type is trivially constructable,
37 // copyable, or movable.
38 template <typename T> class optional {
39 template <typename U> class OptionalStorage {
40 union {
41 char empty;
42 U stored_value;
44 bool in_use;
46 public:
47 LIBC_INLINE ~OptionalStorage() { reset(); }
49 LIBC_INLINE constexpr OptionalStorage() : empty(), in_use(false) {}
51 template <typename... Args>
52 LIBC_INLINE constexpr explicit OptionalStorage(in_place_t, Args &&...args)
53 : stored_value(forward<Args>(args)...), in_use(true) {}
55 LIBC_INLINE void reset() {
56 if (in_use)
57 stored_value.~U();
58 in_use = false;
61 LIBC_INLINE constexpr bool has_value() const { return in_use; }
63 LIBC_INLINE U &value() & { return stored_value; }
64 LIBC_INLINE constexpr U const &value() const & { return stored_value; }
65 LIBC_INLINE U &&value() && { return move(stored_value); }
68 OptionalStorage<T> storage;
70 public:
71 LIBC_INLINE constexpr optional() = default;
72 LIBC_INLINE constexpr optional(nullopt_t) {}
74 LIBC_INLINE constexpr optional(const T &t) : storage(in_place, t) {}
75 LIBC_INLINE constexpr optional(const optional &) = default;
77 LIBC_INLINE constexpr optional(T &&t) : storage(in_place, move(t)) {}
78 LIBC_INLINE constexpr optional(optional &&O) = default;
80 template <typename... ArgTypes>
81 LIBC_INLINE constexpr optional(in_place_t, ArgTypes &&...Args)
82 : storage(in_place, forward<ArgTypes>(Args)...) {}
84 LIBC_INLINE optional &operator=(T &&t) {
85 storage = move(t);
86 return *this;
88 LIBC_INLINE optional &operator=(optional &&) = default;
90 LIBC_INLINE static constexpr optional create(const T *t) {
91 return t ? optional(*t) : optional();
94 LIBC_INLINE optional &operator=(const T &t) {
95 storage = t;
96 return *this;
98 LIBC_INLINE optional &operator=(const optional &) = default;
100 LIBC_INLINE void reset() { storage.reset(); }
102 LIBC_INLINE constexpr const T &value() const & { return storage.value(); }
103 LIBC_INLINE T &value() & { return storage.value(); }
105 LIBC_INLINE constexpr explicit operator bool() const { return has_value(); }
106 LIBC_INLINE constexpr bool has_value() const { return storage.has_value(); }
107 LIBC_INLINE constexpr const T *operator->() const { return &storage.value(); }
108 LIBC_INLINE T *operator->() { return &storage.value(); }
109 LIBC_INLINE constexpr const T &operator*() const & { return value(); }
110 LIBC_INLINE T &operator*() & { return value(); }
112 template <typename U> LIBC_INLINE constexpr T value_or(U &&value) const & {
113 return has_value() ? value() : forward<U>(value);
116 LIBC_INLINE T &&value() && { return move(storage.value()); }
117 LIBC_INLINE T &&operator*() && { return move(storage.value()); }
120 } // namespace cpp
121 } // namespace __llvm_libc
123 #endif // LLVM_LIBC_SRC_SUPPORT_CPP_OPTIONAL_H