Path: blob/main/contrib/llvm-project/libc/src/__support/CPP/optional.h
213799 views
//===-- Standalone implementation of std::optional --------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_OPTIONAL_H9#define LLVM_LIBC_SRC___SUPPORT_CPP_OPTIONAL_H1011#include "src/__support/CPP/type_traits.h"12#include "src/__support/CPP/utility.h"13#include "src/__support/macros/attributes.h"14#include "src/__support/macros/config.h"1516namespace LIBC_NAMESPACE_DECL {17namespace cpp {1819// Trivial nullopt_t struct.20struct nullopt_t {21LIBC_INLINE constexpr explicit nullopt_t() = default;22};2324// nullopt that can be used and returned.25LIBC_INLINE_VAR constexpr nullopt_t nullopt{};2627// This is very simple implementation of the std::optional class. It makes28// several assumptions that the underlying type is trivially constructible,29// copyable, or movable.30template <typename T> class optional {31template <typename U, bool = !is_trivially_destructible<U>::value>32struct OptionalStorage {33union {34char empty;35U stored_value;36};3738bool in_use = false;3940LIBC_INLINE ~OptionalStorage() { reset(); }4142LIBC_INLINE constexpr OptionalStorage() : empty() {}4344template <typename... Args>45LIBC_INLINE constexpr explicit OptionalStorage(in_place_t, Args &&...args)46: stored_value(forward<Args>(args)...) {}4748LIBC_INLINE constexpr void reset() {49if (in_use)50stored_value.~U();51in_use = false;52}53};5455// The only difference is that this type U doesn't have a nontrivial56// destructor.57template <typename U> struct OptionalStorage<U, false> {58union {59char empty;60U stored_value;61};6263bool in_use = false;6465LIBC_INLINE constexpr OptionalStorage() : empty() {}6667template <typename... Args>68LIBC_INLINE constexpr explicit OptionalStorage(in_place_t, Args &&...args)69: stored_value(forward<Args>(args)...) {}7071LIBC_INLINE constexpr void reset() { in_use = false; }72};7374OptionalStorage<T> storage;7576public:77LIBC_INLINE constexpr optional() = default;78LIBC_INLINE constexpr optional(nullopt_t) {}7980LIBC_INLINE constexpr optional(const T &t) : storage(in_place, t) {81storage.in_use = true;82}83LIBC_INLINE constexpr optional(const optional &) = default;8485LIBC_INLINE constexpr optional(T &&t) : storage(in_place, move(t)) {86storage.in_use = true;87}88LIBC_INLINE constexpr optional(optional &&O) = default;8990template <typename... ArgTypes>91LIBC_INLINE constexpr optional(in_place_t, ArgTypes &&...Args)92: storage(in_place, forward<ArgTypes>(Args)...) {93storage.in_use = true;94}9596LIBC_INLINE constexpr optional &operator=(T &&t) {97storage = move(t);98return *this;99}100LIBC_INLINE constexpr optional &operator=(optional &&) = default;101102LIBC_INLINE constexpr optional &operator=(const T &t) {103storage = t;104return *this;105}106LIBC_INLINE constexpr optional &operator=(const optional &) = default;107108LIBC_INLINE constexpr void reset() { storage.reset(); }109110LIBC_INLINE constexpr const T &value() const & {111return storage.stored_value;112}113114LIBC_INLINE constexpr T &value() & { return storage.stored_value; }115116LIBC_INLINE constexpr explicit operator bool() const {117return storage.in_use;118}119LIBC_INLINE constexpr bool has_value() const { return storage.in_use; }120LIBC_INLINE constexpr const T *operator->() const {121return &storage.stored_value;122}123LIBC_INLINE constexpr T *operator->() { return &storage.stored_value; }124LIBC_INLINE constexpr const T &operator*() const & {125return storage.stored_value;126}127LIBC_INLINE constexpr T &operator*() & { return storage.stored_value; }128129LIBC_INLINE constexpr T &&value() && { return move(storage.stored_value); }130LIBC_INLINE constexpr T &&operator*() && {131return move(storage.stored_value);132}133};134135} // namespace cpp136} // namespace LIBC_NAMESPACE_DECL137138#endif // LLVM_LIBC_SRC___SUPPORT_CPP_OPTIONAL_H139140141