1 /* 2 * Copyright (c) 2021-2024 NVIDIA Corporation 3 * 4 * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * https://llvm.org/LICENSE.txt 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #include "__execution_fwd.hpp" 19 20 // include these after __execution_fwd.hpp 21 #include "__concepts.hpp" 22 #include "__type_traits.hpp" 23 24 #include <exception> 25 #include <memory> 26 #include <new> 27 #include <utility> 28 29 namespace stdexec 30 { 31 namespace __opt 32 { 33 struct __bad_optional_access : std::exception 34 { whatstdexec::__opt::__bad_optional_access35 const char* what() const noexcept override 36 { 37 return "stdexec::__optional: bad access"; 38 } 39 }; 40 41 inline constexpr struct __nullopt_t 42 { 43 } __nullopt{}; 44 45 // A simplified version of std::optional for better compile times 46 template <class _Tp> 47 struct __optional 48 { 49 static_assert(destructible<_Tp>); 50 51 union 52 { 53 _Tp __value; 54 }; 55 56 bool __has_value = false; 57 __optionalstdexec::__opt::__optional58 __optional() noexcept {} 59 __optionalstdexec::__opt::__optional60 __optional(__nullopt_t) noexcept {} 61 62 __optional(__optional&&) = delete; // immovable for simplicity's sake 63 64 template <__not_decays_to<__optional> _Up> 65 requires constructible_from<_Tp, _Up> __optionalstdexec::__opt::__optional66 __optional(_Up&& __v) : __value(static_cast<_Up&&>(__v)), __has_value(true) 67 {} 68 69 template <class... _Us> 70 requires constructible_from<_Tp, _Us...> __optionalstdexec::__opt::__optional71 __optional(std::in_place_t, _Us&&... __us) : 72 __value(static_cast<_Us&&>(__us)...), __has_value(true) 73 {} 74 ~__optionalstdexec::__opt::__optional75 ~__optional() 76 { 77 if (__has_value) 78 { 79 std::destroy_at(std::addressof(__value)); 80 } 81 } 82 83 template <class... _Us> 84 requires constructible_from<_Tp, _Us...> emplacestdexec::__opt::__optional85 _Tp& emplace(_Us&&... __us) noexcept( 86 __nothrow_constructible_from<_Tp, _Us...>) 87 { 88 reset(); // sets __has_value to false in case the next line throws 89 ::new (&__value) _Tp{static_cast<_Us&&>(__us)...}; 90 __has_value = true; 91 return __value; 92 } 93 valuestdexec::__opt::__optional94 _Tp& value() & 95 { 96 if (!__has_value) 97 { 98 throw __bad_optional_access(); 99 } 100 return __value; 101 } 102 valuestdexec::__opt::__optional103 const _Tp& value() const& 104 { 105 if (!__has_value) 106 { 107 throw __bad_optional_access(); 108 } 109 return __value; 110 } 111 valuestdexec::__opt::__optional112 _Tp&& value() && 113 { 114 if (!__has_value) 115 { 116 throw __bad_optional_access(); 117 } 118 return static_cast<_Tp&&>(__value); 119 } 120 operator *stdexec::__opt::__optional121 _Tp& operator*() & noexcept 122 { 123 STDEXEC_ASSERT(__has_value); 124 return __value; 125 } 126 operator *stdexec::__opt::__optional127 const _Tp& operator*() const& noexcept 128 { 129 STDEXEC_ASSERT(__has_value); 130 return __value; 131 } 132 operator *stdexec::__opt::__optional133 _Tp&& operator*() && noexcept 134 { 135 STDEXEC_ASSERT(__has_value); 136 return static_cast<_Tp&&>(__value); 137 } 138 operator ->stdexec::__opt::__optional139 _Tp* operator->() & noexcept 140 { 141 STDEXEC_ASSERT(__has_value); 142 return &__value; 143 } 144 operator ->stdexec::__opt::__optional145 const _Tp* operator->() const& noexcept 146 { 147 STDEXEC_ASSERT(__has_value); 148 return &__value; 149 } 150 has_valuestdexec::__opt::__optional151 bool has_value() const noexcept 152 { 153 return __has_value; 154 } 155 resetstdexec::__opt::__optional156 void reset() noexcept 157 { 158 if (__has_value) 159 { 160 std::destroy_at(std::addressof(__value)); 161 __has_value = false; 162 } 163 } 164 }; 165 } // namespace __opt 166 167 using __opt::__bad_optional_access; 168 using __opt::__nullopt; 169 using __opt::__optional; 170 } // namespace stdexec 171