26#ifndef FORTRAN_COMMON_OPTIONAL_H
27#define FORTRAN_COMMON_OPTIONAL_H
29#include "flang/Common/api-attrs.h"
33#if !defined(STD_OPTIONAL_UNSUPPORTED) && \
34 (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__)
35#define STD_OPTIONAL_UNSUPPORTED 1
38#define FORTRAN_OPTIONAL_INLINE_WITH_ATTRS inline RT_API_ATTRS
39#define FORTRAN_OPTIONAL_INLINE inline
40#define FORTRAN_OPTIONAL_INLINE_VAR inline
44#if STD_OPTIONAL_UNSUPPORTED
47 constexpr explicit nullopt_t() =
default;
51FORTRAN_OPTIONAL_INLINE_VAR
constexpr nullopt_t nullopt{};
56template <
typename T>
class optional {
57 template <typename U, bool = !std::is_trivially_destructible<U>::value>
58 struct OptionalStorage {
66 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS ~OptionalStorage() { reset(); }
68 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr OptionalStorage() : empty() {}
70 template <
typename... Args>
71 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr explicit OptionalStorage(
72 std::in_place_t, Args &&...args)
73 : stored_value(std::forward<Args>(args)...) {}
75 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr void reset() {
84 template <
typename U>
struct OptionalStorage<U, false> {
92 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr OptionalStorage() : empty() {}
94 template <
typename... Args>
95 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr explicit OptionalStorage(
96 std::in_place_t, Args &&...args)
97 : stored_value(std::forward<Args>(args)...) {}
99 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr void reset() {
104 OptionalStorage<T> storage;
111 FORTRAN_OPTIONAL_INLINE
constexpr optional() =
default;
112 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr optional(nullopt_t) {}
114 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr optional(
const T &t)
115 : storage(std::in_place, t) {
116 storage.in_use =
true;
118 FORTRAN_OPTIONAL_INLINE
constexpr optional(
const optional &) =
default;
120 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr optional(T &&t)
121 : storage(std::in_place, std::move(t)) {
122 storage.in_use =
true;
124 FORTRAN_OPTIONAL_INLINE
constexpr optional(optional &&O) =
default;
126 template <
typename... ArgTypes>
127 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr optional(
128 std::in_place_t, ArgTypes &&...Args)
129 : storage(std::in_place, std::forward<ArgTypes>(Args)...) {
130 storage.in_use =
true;
133 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr optional &operator=(T &&t) {
134 storage.stored_value = std::move(t);
135 storage.in_use =
true;
139 FORTRAN_OPTIONAL_INLINE
constexpr optional &operator=(optional &&) =
default;
141 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr optional &operator=(
const T &t) {
142 storage.stored_value = t;
143 storage.in_use =
true;
147 FORTRAN_OPTIONAL_INLINE
constexpr optional &operator=(
148 const optional &) =
default;
150 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr void reset() { storage.reset(); }
152 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr const T &value() const & {
153 return storage.stored_value;
156 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr T &value() & {
157 return storage.stored_value;
160 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr explicit operator bool()
const {
161 return storage.in_use;
163 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr bool has_value()
const {
164 return storage.in_use;
166 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr const T *operator->()
const {
167 return &storage.stored_value;
169 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr T *operator->() {
170 return &storage.stored_value;
172 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr const T &operator*() const & {
173 return storage.stored_value;
175 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr T &operator*() & {
176 return storage.stored_value;
179 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr T &&value() && {
180 return std::move(storage.stored_value);
182 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr T &&operator*() && {
183 return std::move(storage.stored_value);
186 template <
typename VT>
187 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr T value_or(
188 VT &&default_value)
const & {
189 return storage.in_use ? storage.stored_value
190 :
static_cast<T
>(std::forward<VT>(default_value));
193 template <
typename VT>
194 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr T value_or(
195 VT &&default_value) && {
196 return storage.in_use ? std::move(storage.stored_value)
197 : static_cast<T>(std::forward<VT>(default_value));
200 template <
typename... ArgTypes>
201 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
202 std::enable_if_t<std::is_constructible_v<T, ArgTypes &&...>, T &>
203 emplace(ArgTypes &&...args) {
205 new (
reinterpret_cast<void *
>(std::addressof(storage.stored_value)))
206 T(std::forward<ArgTypes>(args)...);
207 storage.in_use =
true;
211 template <
typename U = T,
212 std::enable_if_t<(std::is_constructible_v<T, U &&> &&
213 !std::is_same_v<std::decay_t<U>, std::in_place_t> &&
214 !std::is_same_v<std::decay_t<U>, optional> &&
215 std::is_convertible_v<U &&, T>),
217 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
constexpr optional(U &&value) {
218 new (
reinterpret_cast<void *
>(std::addressof(storage.stored_value)))
219 T(std::forward<U>(value));
220 storage.in_use =
true;
223 template <
typename U = T,
224 std::enable_if_t<(std::is_constructible_v<T, U &&> &&
225 !std::is_same_v<std::decay_t<U>, std::in_place_t> &&
226 !std::is_same_v<std::decay_t<U>, optional> &&
227 !std::is_convertible_v<U &&, T>),
229 FORTRAN_OPTIONAL_INLINE_WITH_ATTRS
explicit constexpr optional(U &&value) {
230 new (
reinterpret_cast<void *
>(std::addressof(storage.stored_value)))
231 T(std::forward<U>(value));
232 storage.in_use =
true;
Definition: bit-population-count.h:20