1+ // ==-------- optional.hpp - limited variant 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+ // ===--------------------------------------------------------------------=== //
8+
9+ #pragma once
10+
11+ #include < optional>
12+ #include < type_traits>
13+
14+ namespace sycl {
15+ inline namespace _V1 {
16+ namespace detail {
17+
18+ // ABI-stable implementation of optional to avoid reliance on potentially
19+ // differing implementations of std::optional when crossing the library
20+ // boundary.
21+ template <typename T> class optional {
22+ public:
23+ constexpr optional () noexcept {}
24+ constexpr optional (std::nullopt_t ) noexcept : optional() {}
25+
26+ template <typename U>
27+ constexpr optional (const optional<U> &Other)
28+ : ContainsValue{Other.ContainsValue } {
29+ new (Storage) T (Other.Value );
30+ }
31+ template <typename U>
32+ constexpr optional (optional<U> &&Other)
33+ : ContainsValue{std::move (Other.ContainsValue )} {
34+ new (Storage) T (std::move (Other.Value ));
35+ }
36+
37+ constexpr optional (T &&Value) : ContainsValue{true } {
38+ new (Storage) T (std::move (Value));
39+ }
40+
41+ constexpr optional (const T &Value) : ContainsValue{true } {
42+ new (Storage) T (Value);
43+ }
44+
45+ template <typename U>
46+ constexpr optional (const std::optional<U> &Other) : ContainsValue{Other} {
47+ if (Other)
48+ new (Storage) T (*Other);
49+ }
50+
51+ ~optional () {
52+ if (has_value ())
53+ reinterpret_cast <T *>(Storage)->~T ();
54+ }
55+
56+ optional &operator =(std::nullopt_t ) noexcept {
57+ if (has_value ())
58+ reinterpret_cast <T *>(Storage)->~T ();
59+ ContainsValue = false ;
60+ return *this ;
61+ }
62+
63+ template <typename U> optional &operator =(const optional<U> &Other) {
64+ if (has_value ())
65+ reinterpret_cast <T *>(Storage)->~T ();
66+ ContainsValue = Other;
67+ new (Storage) T (Other.Value );
68+ return *this ;
69+ }
70+ template <typename U> optional &operator =(optional<U> &&Other) noexcept {
71+ if (has_value ())
72+ reinterpret_cast <T *>(Storage)->~T ();
73+ ContainsValue = Other;
74+ new (Storage) T (std::move (Other.Value ));
75+ return *this ;
76+ }
77+
78+ optional &operator =(T &&Value){
79+ if (has_value ())
80+ reinterpret_cast <T *>(Storage)->~T ();
81+ ContainsValue = true ;
82+ new (Storage) T (std::move (Value));
83+ return *this ;
84+ }
85+
86+ optional &operator =(const T &Value){
87+ if (has_value ())
88+ reinterpret_cast <T *>(Storage)->~T ();
89+ ContainsValue = true ;
90+ new (Storage) T (Value);
91+ return *this ;
92+ }
93+
94+ template <typename U>
95+ optional &operator =(const std::optional<U> &Other) {
96+ if (has_value ())
97+ reinterpret_cast <T *>(Storage)->~T ();
98+ ContainsValue = Other;
99+ if (Other)
100+ new (Storage) T (*Other);
101+ return *this ;
102+ }
103+
104+ constexpr bool has_value () const noexcept { return ContainsValue; }
105+ constexpr explicit operator bool () const noexcept { return has_value (); }
106+
107+ constexpr T &value () & {
108+ if (!has_value ())
109+ throw std::bad_optional_access{};
110+ return *reinterpret_cast <T *>(Storage);
111+ }
112+ constexpr const T &value () const & {
113+ if (!has_value ())
114+ throw std::bad_optional_access{};
115+ return *reinterpret_cast <const T *>(Storage);
116+ }
117+ constexpr T &&value() && {
118+ if (!has_value ())
119+ throw std::bad_optional_access{};
120+ return std::move (*reinterpret_cast <T *>(Storage));
121+ }
122+ constexpr const T &&value() const && {
123+ if (!has_value ())
124+ throw std::bad_optional_access{};
125+ return std::move (*reinterpret_cast <const T *>(Storage));
126+ }
127+
128+ template <class U > constexpr T value_or (U &&DefaultVal) {
129+ return has_value () ? value () : static_cast <T>(std::forward<U>(DefaultVal));
130+ }
131+ template <class U > constexpr T value_or (U &&DefaultVal) const {
132+ return has_value () ? std::move (value ())
133+ : static_cast <T>(std::forward<U>(DefaultVal));
134+ }
135+
136+ constexpr T &operator *() & { return value (); }
137+ constexpr const T &operator *() const & { return value (); }
138+ constexpr T &&operator *() && { return value (); }
139+ constexpr const T &&operator *() const && { return value (); }
140+
141+ private:
142+ alignas (alignof (T)) char Storage[sizeof (T)] = {0 };
143+ bool ContainsValue = false ;
144+ };
145+
146+ } // namespace detail
147+ } // namespace _V1
148+ } // namespace sycl
0 commit comments