brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.1 KiB · aed2269 Raw
140 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_OPTIONAL_H10#define LLVM_LIBC_SRC___SUPPORT_CPP_OPTIONAL_H11 12#include "src/__support/CPP/type_traits.h"13#include "src/__support/CPP/utility.h"14#include "src/__support/macros/attributes.h"15#include "src/__support/macros/config.h"16 17namespace LIBC_NAMESPACE_DECL {18namespace cpp {19 20// Trivial nullopt_t struct.21struct nullopt_t {22  LIBC_INLINE constexpr explicit nullopt_t() = default;23};24 25// nullopt that can be used and returned.26LIBC_INLINE_VAR constexpr nullopt_t nullopt{};27 28// This is very simple implementation of the std::optional class. It makes29// several assumptions that the underlying type is trivially constructible,30// copyable, or movable.31template <typename T> class optional {32  template <typename U, bool = !is_trivially_destructible<U>::value>33  struct OptionalStorage {34    union {35      char empty;36      U stored_value;37    };38 39    bool in_use = false;40 41    LIBC_INLINE ~OptionalStorage() { reset(); }42 43    LIBC_INLINE constexpr OptionalStorage() : empty() {}44 45    template <typename... Args>46    LIBC_INLINE constexpr explicit OptionalStorage(in_place_t, Args &&...args)47        : stored_value(forward<Args>(args)...) {}48 49    LIBC_INLINE constexpr void reset() {50      if (in_use)51        stored_value.~U();52      in_use = false;53    }54  };55 56  // The only difference is that this type U doesn't have a nontrivial57  // destructor.58  template <typename U> struct OptionalStorage<U, false> {59    union {60      char empty;61      U stored_value;62    };63 64    bool in_use = false;65 66    LIBC_INLINE constexpr OptionalStorage() : empty() {}67 68    template <typename... Args>69    LIBC_INLINE constexpr explicit OptionalStorage(in_place_t, Args &&...args)70        : stored_value(forward<Args>(args)...) {}71 72    LIBC_INLINE constexpr void reset() { in_use = false; }73  };74 75  OptionalStorage<T> storage;76 77public:78  LIBC_INLINE constexpr optional() = default;79  LIBC_INLINE constexpr optional(nullopt_t) {}80 81  LIBC_INLINE constexpr optional(const T &t) : storage(in_place, t) {82    storage.in_use = true;83  }84  LIBC_INLINE constexpr optional(const optional &) = default;85 86  LIBC_INLINE constexpr optional(T &&t) : storage(in_place, move(t)) {87    storage.in_use = true;88  }89  LIBC_INLINE constexpr optional(optional &&O) = default;90 91  template <typename... ArgTypes>92  LIBC_INLINE constexpr optional(in_place_t, ArgTypes &&...Args)93      : storage(in_place, forward<ArgTypes>(Args)...) {94    storage.in_use = true;95  }96 97  LIBC_INLINE constexpr optional &operator=(T &&t) {98    storage = move(t);99    return *this;100  }101  LIBC_INLINE constexpr optional &operator=(optional &&) = default;102 103  LIBC_INLINE constexpr optional &operator=(const T &t) {104    storage = t;105    return *this;106  }107  LIBC_INLINE constexpr optional &operator=(const optional &) = default;108 109  LIBC_INLINE constexpr void reset() { storage.reset(); }110 111  LIBC_INLINE constexpr const T &value() const & {112    return storage.stored_value;113  }114 115  LIBC_INLINE constexpr T &value() & { return storage.stored_value; }116 117  LIBC_INLINE constexpr explicit operator bool() const {118    return storage.in_use;119  }120  LIBC_INLINE constexpr bool has_value() const { return storage.in_use; }121  LIBC_INLINE constexpr const T *operator->() const {122    return &storage.stored_value;123  }124  LIBC_INLINE constexpr T *operator->() { return &storage.stored_value; }125  LIBC_INLINE constexpr const T &operator*() const & {126    return storage.stored_value;127  }128  LIBC_INLINE constexpr T &operator*() & { return storage.stored_value; }129 130  LIBC_INLINE constexpr T &&value() && { return move(storage.stored_value); }131  LIBC_INLINE constexpr T &&operator*() && {132    return move(storage.stored_value);133  }134};135 136} // namespace cpp137} // namespace LIBC_NAMESPACE_DECL138 139#endif // LLVM_LIBC_SRC___SUPPORT_CPP_OPTIONAL_H140