1 // The MIT License (MIT)
2 
3 // Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
4 
5 // Permission is hereby granted, free of charge, to any person obtaining a copy of
6 // this software and associated documentation files (the "Software"), to deal in
7 // the Software without restriction, including without limitation the rights to
8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 // the Software, and to permit persons to whom the Software is furnished to do so,
10 // subject to the following conditions:
11 
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22 // Taken from: TartanLlama/optional on Github, because
23 // holy shit am I done dealing with C++11 constexpr
24 
25 ///
26 // optional - An implementation of std::optional with extensions
27 // Written in 2017 by Simon Brand (@TartanLlama)
28 //
29 // To the extent possible under law, the author(s) have dedicated all
30 // copyright and related and neighboring rights to this software to the
31 // public domain worldwide. This software is distributed without any warranty.
32 //
33 // You should have received a copy of the CC0 Public Domain Dedication
34 // along with this software. If not, see
35 // <http://creativecommons.org/publicdomain/zero/1.0/>.
36 ///
37 
38 #ifndef SOL_TL_OPTIONAL_HPP
39 #define SOL_TL_OPTIONAL_HPP
40 
41 #include <sol/version.hpp>
42 
43 #include <sol/in_place.hpp>
44 
45 #define SOL_TL_OPTIONAL_VERSION_MAJOR 0
46 #define SOL_TL_OPTIONAL_VERSION_MINOR 5
47 
48 #include <exception>
49 #include <functional>
50 #include <new>
51 #include <type_traits>
52 #include <utility>
53 #include <cstdlib>
54 #include <optional>
55 
56 #if (defined(_MSC_VER) && _MSC_VER == 1900)
57 #define SOL_TL_OPTIONAL_MSVC2015
58 #endif
59 
60 #if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__))
61 #define SOL_TL_OPTIONAL_GCC49
62 #endif
63 
64 #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && !defined(__clang__))
65 #define SOL_TL_OPTIONAL_GCC54
66 #endif
67 
68 #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && !defined(__clang__))
69 #define SOL_TL_OPTIONAL_GCC55
70 #endif
71 
72 #if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__))
73 // GCC < 5 doesn't support overloading on const&& for member functions
74 #define SOL_TL_OPTIONAL_NO_CONSTRR
75 
76 // GCC < 5 doesn't support some standard C++11 type traits
77 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::has_trivial_copy_constructor<T>::value
78 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign<T>::value
79 
80 // This one will be different for GCC 5.7 if it's ever supported
81 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
82 
83 // GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks std::vector
84 // for non-copyable types
85 #elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))
86 #ifndef SOL_TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
87 #define SOL_TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
88 namespace sol { namespace detail {
89 	template <class T>
90 	struct is_trivially_copy_constructible : std::is_trivially_copy_constructible<T> { };
91 #ifdef _GLIBCXX_VECTOR
92 	template <class T, class A>
93 	struct is_trivially_copy_constructible<std::vector<T, A>> : std::is_trivially_copy_constructible<T> { };
94 #endif
95 }} // namespace sol::detail
96 #endif
97 
98 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) sol::detail::is_trivially_copy_constructible<T>::value
99 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable<T>::value
100 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
101 #else
102 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::is_trivially_copy_constructible<T>::value
103 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable<T>::value
104 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
105 #endif
106 
107 #if __cplusplus > 201103L
108 #define SOL_TL_OPTIONAL_CXX14
109 #endif
110 
111 // constexpr implies const in C++11, not C++14
112 #if (__cplusplus == 201103L || defined(SOL_TL_OPTIONAL_MSVC2015) || defined(SOL_TL_OPTIONAL_GCC49))
113 /// \exclude
114 #define SOL_TL_OPTIONAL_11_CONSTEXPR
115 #else
116    /// \exclude
117 #define SOL_TL_OPTIONAL_11_CONSTEXPR constexpr
118 #endif
119 
120 namespace sol {
121 #ifndef SOL_TL_MONOSTATE_INPLACE_MUTEX
122 #define SOL_TL_MONOSTATE_INPLACE_MUTEX
123 	/// \brief Used to represent an optional with no data; essentially a bool
124 	class monostate { };
125 #endif
126 
127 	template <class T>
128 	class optional;
129 
130 	/// \exclude
131 	namespace detail {
132 #ifndef SOL_TL_TRAITS_MUTEX
133 #define SOL_TL_TRAITS_MUTEX
134 		// C++14-style aliases for brevity
135 		template <class T>
136 		using remove_const_t = typename std::remove_const<T>::type;
137 		template <class T>
138 		using remove_reference_t = typename std::remove_reference<T>::type;
139 		template <class T>
140 		using decay_t = typename std::decay<T>::type;
141 		template <bool E, class T = void>
142 		using enable_if_t = typename std::enable_if<E, T>::type;
143 		template <bool B, class T, class F>
144 		using conditional_t = typename std::conditional<B, T, F>::type;
145 
146 		// std::conjunction from C++17
147 		template <class...>
148 		struct conjunction : std::true_type { };
149 		template <class B>
150 		struct conjunction<B> : B { };
151 		template <class B, class... Bs>
152 		struct conjunction<B, Bs...> : std::conditional<bool(B::value), conjunction<Bs...>, B>::type { };
153 
154 #if defined(_LIBCPP_VERSION) && __cplusplus == 201103L
155 #define SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND
156 #endif
157 
158 // In C++11 mode, there's an issue in libc++'s std::mem_fn
159 // which results in a hard-error when using it in a noexcept expression
160 // in some cases. This is a check to workaround the common failing case.
161 #ifdef SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND
162 		template <class T>
163 		struct is_pointer_to_non_const_member_func : std::false_type { };
164 		template <class T, class Ret, class... Args>
165 		struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)> : std::true_type { };
166 		template <class T, class Ret, class... Args>
167 		struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)&> : std::true_type { };
168 		template <class T, class Ret, class... Args>
169 		struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &&> : std::true_type { };
170 		template <class T, class Ret, class... Args>
171 		struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile> : std::true_type { };
172 		template <class T, class Ret, class... Args>
173 		struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile&> : std::true_type { };
174 		template <class T, class Ret, class... Args>
175 		struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile&&> : std::true_type { };
176 
177 		template <class T>
178 		struct is_const_or_const_ref : std::false_type { };
179 		template <class T>
180 		struct is_const_or_const_ref<T const&> : std::true_type { };
181 		template <class T>
182 		struct is_const_or_const_ref<T const> : std::true_type { };
183 #endif
184 
185 		// std::invoke from C++17
186 		// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround
187 		template <typename Fn, typename... Args,
188 #ifdef SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND
189 		     typename = enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value && is_const_or_const_ref<Args...>::value)>,
190 #endif
191 		     typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>, int = 0>
invoke(Fn && f,Args &&...args)192 		constexpr auto invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
193 		     -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {
194 			return std::mem_fn(f)(std::forward<Args>(args)...);
195 		}
196 
197 		template <typename Fn, typename... Args, typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>>
invoke(Fn && f,Args &&...args)198 		constexpr auto invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
199 		     -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {
200 			return std::forward<Fn>(f)(std::forward<Args>(args)...);
201 		}
202 
203 		// std::invoke_result from C++17
204 		template <class F, class, class... Us>
205 		struct invoke_result_impl;
206 
207 		template <class F, class... Us>
208 		struct invoke_result_impl<F, decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()), Us...> {
209 			using type = decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...));
210 		};
211 
212 		template <class F, class... Us>
213 		using invoke_result = invoke_result_impl<F, void, Us...>;
214 
215 		template <class F, class... Us>
216 		using invoke_result_t = typename invoke_result<F, Us...>::type;
217 #endif
218 
219 		// std::void_t from C++17
220 		template <class...>
221 		struct voider {
222 			using type = void;
223 		};
224 		template <class... Ts>
225 		using void_t = typename voider<Ts...>::type;
226 
227 		// Trait for checking if a type is a sol::optional
228 		template <class T>
229 		struct is_optional_impl : std::false_type { };
230 		template <class T>
231 		struct is_optional_impl<optional<T>> : std::true_type { };
232 		template <class T>
233 		using is_optional = is_optional_impl<decay_t<T>>;
234 
235 		// Change void to sol::monostate
236 		template <class U>
237 		using fixup_void = conditional_t<std::is_void<U>::value, monostate, U>;
238 
239 		template <class F, class U, class = invoke_result_t<F, U>>
240 		using get_map_return = optional<fixup_void<invoke_result_t<F, U>>>;
241 
242 		// Check if invoking F for some Us returns void
243 		template <class F, class = void, class... U>
244 		struct returns_void_impl;
245 		template <class F, class... U>
246 		struct returns_void_impl<F, void_t<invoke_result_t<F, U...>>, U...> : std::is_void<invoke_result_t<F, U...>> { };
247 		template <class F, class... U>
248 		using returns_void = returns_void_impl<F, void, U...>;
249 
250 		template <class T, class... U>
251 		using enable_if_ret_void = enable_if_t<returns_void<T&&, U...>::value>;
252 
253 		template <class T, class... U>
254 		using disable_if_ret_void = enable_if_t<!returns_void<T&&, U...>::value>;
255 
256 		template <class T, class U>
257 		using enable_forward_value = detail::enable_if_t<std::is_constructible<T, U&&>::value && !std::is_same<detail::decay_t<U>, in_place_t>::value
258 		     && !std::is_same<optional<T>, detail::decay_t<U>>::value>;
259 
260 		template <class T, class U, class Other>
261 		using enable_from_other = detail::enable_if_t<std::is_constructible<T, Other>::value && !std::is_constructible<T, optional<U>&>::value
262 		     && !std::is_constructible<T, optional<U>&&>::value && !std::is_constructible<T, const optional<U>&>::value
263 		     && !std::is_constructible<T, const optional<U>&&>::value && !std::is_convertible<optional<U>&, T>::value
264 		     && !std::is_convertible<optional<U>&&, T>::value && !std::is_convertible<const optional<U>&, T>::value
265 		     && !std::is_convertible<const optional<U>&&, T>::value>;
266 
267 		template <class T, class U>
268 		using enable_assign_forward = detail::enable_if_t<!std::is_same<optional<T>, detail::decay_t<U>>::value
269 		     && !detail::conjunction<std::is_scalar<T>, std::is_same<T, detail::decay_t<U>>>::value && std::is_constructible<T, U>::value
270 		     && std::is_assignable<T&, U>::value>;
271 
272 		template <class T, class U, class Other>
273 		using enable_assign_from_other = detail::enable_if_t<std::is_constructible<T, Other>::value && std::is_assignable<T&, Other>::value
274 		     && !std::is_constructible<T, optional<U>&>::value && !std::is_constructible<T, optional<U>&&>::value
275 		     && !std::is_constructible<T, const optional<U>&>::value && !std::is_constructible<T, const optional<U>&&>::value
276 		     && !std::is_convertible<optional<U>&, T>::value && !std::is_convertible<optional<U>&&, T>::value
277 		     && !std::is_convertible<const optional<U>&, T>::value && !std::is_convertible<const optional<U>&&, T>::value
278 		     && !std::is_assignable<T&, optional<U>&>::value && !std::is_assignable<T&, optional<U>&&>::value
279 		     && !std::is_assignable<T&, const optional<U>&>::value && !std::is_assignable<T&, const optional<U>&&>::value>;
280 
281 #ifdef _MSC_VER
282 		// TODO make a version which works with MSVC
283 		template <class T, class U = T>
284 		struct is_swappable : std::true_type { };
285 
286 		template <class T, class U = T>
287 		struct is_nothrow_swappable : std::true_type { };
288 #else
289 		// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
290 		namespace swap_adl_tests {
291 			// if swap ADL finds this then it would call std::swap otherwise (same
292 			// signature)
293 			struct tag { };
294 
295 			template <class T>
296 			tag swap(T&, T&);
297 			template <class T, std::size_t N>
298 			tag swap(T (&a)[N], T (&b)[N]);
299 
300 			// helper functions to test if an unqualified swap is possible, and if it
301 			// becomes std::swap
302 			template <class, class>
303 			std::false_type can_swap(...) noexcept(false);
304 			template <class T, class U, class = decltype(swap(std::declval<T&>(), std::declval<U&>()))>
305 			std::true_type can_swap(int) noexcept(noexcept(swap(std::declval<T&>(), std::declval<U&>())));
306 
307 			template <class, class>
308 			std::false_type uses_std(...);
309 			template <class T, class U>
310 			std::is_same<decltype(swap(std::declval<T&>(), std::declval<U&>())), tag> uses_std(int);
311 
312 			template <class T>
313 			struct is_std_swap_noexcept
314 			: std::integral_constant<bool, std::is_nothrow_move_constructible<T>::value && std::is_nothrow_move_assignable<T>::value> { };
315 
316 			template <class T, std::size_t N>
317 			struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> { };
318 
319 			template <class T, class U>
320 			struct is_adl_swap_noexcept : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> { };
321 		} // namespace swap_adl_tests
322 
323 		template <class T, class U = T>
324 		struct is_swappable : std::integral_constant<bool,
325 		                           decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value
326 		                                && (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value
327 		                                     || (std::is_move_assignable<T>::value && std::is_move_constructible<T>::value))> { };
328 
329 		template <class T, std::size_t N>
330 		struct is_swappable<T[N], T[N]> : std::integral_constant<bool,
331 		                                       decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value
332 		                                            && (!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value || is_swappable<T, T>::value)> { };
333 
334 		template <class T, class U = T>
335 		struct is_nothrow_swappable
336 		: std::integral_constant<bool,
337 		       is_swappable<T, U>::value
338 		            && ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value&& detail::swap_adl_tests::is_std_swap_noexcept<T>::value)
339 		                 || (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value&& detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> { };
340 #endif
341 
342 		// The storage base manages the actual storage, and correctly propagates
343 		// trivial destroyion from T. This case is for when T is not trivially
344 		// destructible.
345 		template <class T, bool = ::std::is_trivially_destructible<T>::value>
346 		struct optional_storage_base {
optional_storage_basesol::detail::optional_storage_base347 			SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept : m_dummy(), m_has_value(false) {
348 			}
349 
350 			template <class... U>
optional_storage_basesol::detail::optional_storage_base351 			SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U&&... u) : m_value(std::forward<U>(u)...), m_has_value(true) {
352 			}
353 
~optional_storage_basesol::detail::optional_storage_base354 			~optional_storage_base() {
355 				if (m_has_value) {
356 					m_value.~T();
357 					m_has_value = false;
358 				}
359 			}
360 
361 			struct dummy { };
362 			union {
363 				dummy m_dummy;
364 				T m_value;
365 			};
366 
367 			bool m_has_value;
368 		};
369 
370 		// This case is for when T is trivially destructible.
371 		template <class T>
372 		struct optional_storage_base<T, true> {
optional_storage_basesol::detail::optional_storage_base373 			SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept : m_dummy(), m_has_value(false) {
374 			}
375 
376 			template <class... U>
optional_storage_basesol::detail::optional_storage_base377 			SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U&&... u) : m_value(std::forward<U>(u)...), m_has_value(true) {
378 			}
379 
380 			// No destructor, so this class is trivially destructible
381 
382 			struct dummy { };
383 			union {
384 				dummy m_dummy;
385 				T m_value;
386 			};
387 
388 			bool m_has_value = false;
389 		};
390 
391 		// This base class provides some handy member functions which can be used in
392 		// further derived classes
393 		template <class T>
394 		struct optional_operations_base : optional_storage_base<T> {
395 			using optional_storage_base<T>::optional_storage_base;
396 
hard_resetsol::detail::optional_operations_base397 			void hard_reset() noexcept {
398 				get().~T();
399 				this->m_has_value = false;
400 			}
401 
402 			template <class... Args>
constructsol::detail::optional_operations_base403 			void construct(Args&&... args) noexcept {
404 				new (std::addressof(this->m_value)) T(std::forward<Args>(args)...);
405 				this->m_has_value = true;
406 			}
407 
408 			template <class Opt>
assignsol::detail::optional_operations_base409 			void assign(Opt&& rhs) {
410 				if (this->has_value()) {
411 					if (rhs.has_value()) {
412 						this->m_value = std::forward<Opt>(rhs).get();
413 					}
414 					else {
415 						this->m_value.~T();
416 						this->m_has_value = false;
417 					}
418 				}
419 
420 				else if (rhs.has_value()) {
421 					construct(std::forward<Opt>(rhs).get());
422 				}
423 			}
424 
has_valuesol::detail::optional_operations_base425 			bool has_value() const {
426 				return this->m_has_value;
427 			}
428 
getsol::detail::optional_operations_base429 			SOL_TL_OPTIONAL_11_CONSTEXPR T& get() & {
430 				return this->m_value;
431 			}
getsol::detail::optional_operations_base432 			SOL_TL_OPTIONAL_11_CONSTEXPR const T& get() const& {
433 				return this->m_value;
434 			}
getsol::detail::optional_operations_base435 			SOL_TL_OPTIONAL_11_CONSTEXPR T&& get() && {
436 				return std::move(this->m_value);
437 			}
438 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
getsol::detail::optional_operations_base439 			constexpr const T&& get() const&& {
440 				return std::move(this->m_value);
441 			}
442 #endif
443 		};
444 
445 		// This class manages conditionally having a trivial copy constructor
446 		// This specialization is for when T is trivially copy constructible
447 		template <class T, bool = SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>
448 		struct optional_copy_base : optional_operations_base<T> {
449 			using optional_operations_base<T>::optional_operations_base;
450 		};
451 
452 		// This specialization is for when T is not trivially copy constructible
453 		template <class T>
454 		struct optional_copy_base<T, false> : optional_operations_base<T> {
455 			using base_t = optional_operations_base<T>;
456 
457 			using base_t::base_t;
458 
459 			optional_copy_base() = default;
optional_copy_basesol::detail::optional_copy_base460 			optional_copy_base(const optional_copy_base& rhs) : base_t() {
461 				if (rhs.has_value()) {
462 					this->construct(rhs.get());
463 				}
464 				else {
465 					this->m_has_value = false;
466 				}
467 			}
468 
469 			optional_copy_base(optional_copy_base&& rhs) = default;
470 			optional_copy_base& operator=(const optional_copy_base& rhs) = default;
471 			optional_copy_base& operator=(optional_copy_base&& rhs) = default;
472 		};
473 
474 // This class manages conditionally having a trivial move constructor
475 // Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
476 // doesn't implement an analogue to std::is_trivially_move_constructible. We
477 // have to make do with a non-trivial move constructor even if T is trivially
478 // move constructible
479 #ifndef SOL_TL_OPTIONAL_GCC49
480 		template <class T, bool = std::is_trivially_move_constructible<T>::value>
481 		struct optional_move_base : optional_copy_base<T> {
482 			using optional_copy_base<T>::optional_copy_base;
483 		};
484 #else
485 		template <class T, bool = false>
486 		struct optional_move_base;
487 #endif
488 		template <class T>
489 		struct optional_move_base<T, false> : optional_copy_base<T> {
490 			using optional_copy_base<T>::optional_copy_base;
491 
492 			optional_move_base() = default;
493 			optional_move_base(const optional_move_base& rhs) = default;
494 
optional_move_basesol::detail::optional_move_base495 			optional_move_base(optional_move_base&& rhs) noexcept(std::is_nothrow_move_constructible<T>::value) {
496 				if (rhs.has_value()) {
497 					this->construct(std::move(rhs.get()));
498 				}
499 				else {
500 					this->m_has_value = false;
501 				}
502 			}
503 			optional_move_base& operator=(const optional_move_base& rhs) = default;
504 			optional_move_base& operator=(optional_move_base&& rhs) = default;
505 		};
506 
507 		// This class manages conditionally having a trivial copy assignment operator
508 		template <class T,
509 		     bool = SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) && SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)
510 		          && SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T)>
511 		struct optional_copy_assign_base : optional_move_base<T> {
512 			using optional_move_base<T>::optional_move_base;
513 		};
514 
515 		template <class T>
516 		struct optional_copy_assign_base<T, false> : optional_move_base<T> {
517 			using optional_move_base<T>::optional_move_base;
518 
519 			optional_copy_assign_base() = default;
520 			optional_copy_assign_base(const optional_copy_assign_base& rhs) = default;
521 
522 			optional_copy_assign_base(optional_copy_assign_base&& rhs) = default;
operator =sol::detail::optional_copy_assign_base523 			optional_copy_assign_base& operator=(const optional_copy_assign_base& rhs) {
524 				this->assign(rhs);
525 				return *this;
526 			}
527 			optional_copy_assign_base& operator=(optional_copy_assign_base&& rhs) = default;
528 		};
529 
530 // This class manages conditionally having a trivial move assignment operator
531 // Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
532 // doesn't implement an analogue to std::is_trivially_move_assignable. We have
533 // to make do with a non-trivial move assignment operator even if T is trivially
534 // move assignable
535 #ifndef SOL_TL_OPTIONAL_GCC49
536 		template <class T,
537 		     bool = std::is_trivially_destructible<T>::value&& std::is_trivially_move_constructible<T>::value&& std::is_trivially_move_assignable<T>::value>
538 		struct optional_move_assign_base : optional_copy_assign_base<T> {
539 			using optional_copy_assign_base<T>::optional_copy_assign_base;
540 		};
541 #else
542 		template <class T, bool = false>
543 		struct optional_move_assign_base;
544 #endif
545 
546 		template <class T>
547 		struct optional_move_assign_base<T, false> : optional_copy_assign_base<T> {
548 			using optional_copy_assign_base<T>::optional_copy_assign_base;
549 
550 			optional_move_assign_base() = default;
551 			optional_move_assign_base(const optional_move_assign_base& rhs) = default;
552 
553 			optional_move_assign_base(optional_move_assign_base&& rhs) = default;
554 
555 			optional_move_assign_base& operator=(const optional_move_assign_base& rhs) = default;
556 
operator =sol::detail::optional_move_assign_base557 			optional_move_assign_base& operator=(optional_move_assign_base&& rhs) noexcept(
558 			     std::is_nothrow_move_constructible<T>::value&& std::is_nothrow_move_assignable<T>::value) {
559 				this->assign(std::move(rhs));
560 				return *this;
561 			}
562 		};
563 
564 		// optional_delete_ctor_base will conditionally delete copy and move
565 		// constructors depending on whether T is copy/move constructible
566 		template <class T, bool EnableCopy = std::is_copy_constructible<T>::value, bool EnableMove = std::is_move_constructible<T>::value>
567 		struct optional_delete_ctor_base {
568 			optional_delete_ctor_base() = default;
569 			optional_delete_ctor_base(const optional_delete_ctor_base&) = default;
570 			optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = default;
571 			optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default;
572 			optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default;
573 		};
574 
575 		template <class T>
576 		struct optional_delete_ctor_base<T, true, false> {
577 			optional_delete_ctor_base() = default;
578 			optional_delete_ctor_base(const optional_delete_ctor_base&) = default;
579 			optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = delete;
580 			optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default;
581 			optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default;
582 		};
583 
584 		template <class T>
585 		struct optional_delete_ctor_base<T, false, true> {
586 			optional_delete_ctor_base() = default;
587 			optional_delete_ctor_base(const optional_delete_ctor_base&) = delete;
588 			optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = default;
589 			optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default;
590 			optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default;
591 		};
592 
593 		template <class T>
594 		struct optional_delete_ctor_base<T, false, false> {
595 			optional_delete_ctor_base() = default;
596 			optional_delete_ctor_base(const optional_delete_ctor_base&) = delete;
597 			optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = delete;
598 			optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default;
599 			optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default;
600 		};
601 
602 		// optional_delete_assign_base will conditionally delete copy and move
603 		// constructors depending on whether T is copy/move constructible + assignable
604 		template <class T, bool EnableCopy = (std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value),
605 		     bool EnableMove = (std::is_move_constructible<T>::value && std::is_move_assignable<T>::value)>
606 		struct optional_delete_assign_base {
607 			optional_delete_assign_base() = default;
608 			optional_delete_assign_base(const optional_delete_assign_base&) = default;
609 			optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default;
610 			optional_delete_assign_base& operator=(const optional_delete_assign_base&) = default;
611 			optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = default;
612 		};
613 
614 		template <class T>
615 		struct optional_delete_assign_base<T, true, false> {
616 			optional_delete_assign_base() = default;
617 			optional_delete_assign_base(const optional_delete_assign_base&) = default;
618 			optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default;
619 			optional_delete_assign_base& operator=(const optional_delete_assign_base&) = default;
620 			optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = delete;
621 		};
622 
623 		template <class T>
624 		struct optional_delete_assign_base<T, false, true> {
625 			optional_delete_assign_base() = default;
626 			optional_delete_assign_base(const optional_delete_assign_base&) = default;
627 			optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default;
628 			optional_delete_assign_base& operator=(const optional_delete_assign_base&) = delete;
629 			optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = default;
630 		};
631 
632 		template <class T>
633 		struct optional_delete_assign_base<T, false, false> {
634 			optional_delete_assign_base() = default;
635 			optional_delete_assign_base(const optional_delete_assign_base&) = default;
636 			optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default;
637 			optional_delete_assign_base& operator=(const optional_delete_assign_base&) = delete;
638 			optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = delete;
639 		};
640 
641 	} // namespace detail
642 
643 	/// \brief A tag type to represent an empty optional
644 	using nullopt_t = std::nullopt_t;
645 
646 	/// \brief Represents an empty optional
647 	/// \synopsis static constexpr nullopt_t nullopt;
648 	///
649 	/// *Examples*:
650 	/// ```
651 	/// sol::optional<int> a = sol::nullopt;
652 	/// void foo (sol::optional<int>);
653 	/// foo(sol::nullopt); //pass an empty optional
654 	/// ```
655 	using std::nullopt;
656 
657 	/// @brief An exception for when an optional is accessed through specific methods while it is not engaged.
658 	class bad_optional_access : public std::exception {
659 	public:
660 		/// @brief Default-constructs an optional exception.
661 		bad_optional_access() = default;
662 		/// @brief Returns a pointer to a null-terminated string containing the reason for the exception.
what() const663 		const char* what() const noexcept override {
664 			return "Optional has no value";
665 		}
666 	};
667 
668 	/// An optional object is an object that contains the storage for another
669 	/// object and manages the lifetime of this contained object, if any. The
670 	/// contained object may be initialized after the optional object has been
671 	/// initialized, and may be destroyed before the optional object has been
672 	/// destroyed. The initialization state of the contained object is tracked by
673 	/// the optional object.
674 	template <class T>
675 	class optional : private detail::optional_move_assign_base<T>,
676 	                 private detail::optional_delete_ctor_base<T>,
677 	                 private detail::optional_delete_assign_base<T> {
678 		using base = detail::optional_move_assign_base<T>;
679 
680 		static_assert(!std::is_same<T, in_place_t>::value, "instantiation of optional with in_place_t is ill-formed");
681 		static_assert(!std::is_same<detail::decay_t<T>, nullopt_t>::value, "instantiation of optional with nullopt_t is ill-formed");
682 
683 	public:
684 // The different versions for C++14 and 11 are needed because deduced return
685 // types are not SFINAE-safe. This provides better support for things like
686 // generic lambdas. C.f.
687 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
688 #if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55)
689 		/// \group and_then
690 		/// Carries out some operation which returns an optional on the stored
691 		/// object if there is one. \requires `std::invoke(std::forward<F>(f),
692 		/// value())` returns a `std::optional<U>` for some `U`. \returns Let `U` be
693 		/// the result of `std::invoke(std::forward<F>(f), value())`. Returns a
694 		/// `std::optional<U>`. The return value is empty if `*this` is empty,
695 		/// otherwise the return value of `std::invoke(std::forward<F>(f), value())`
696 		/// is returned.
697 		/// \group and_then
698 		/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
699 		template <class F>
and_then(F && f)700 		SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) & {
701 			using result = detail::invoke_result_t<F, T&>;
702 			static_assert(detail::is_optional<result>::value, "F must return an optional");
703 
704 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
705 		}
706 
707 		/// \group and_then
708 		/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
709 		template <class F>
and_then(F && f)710 		SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) && {
711 			using result = detail::invoke_result_t<F, T&&>;
712 			static_assert(detail::is_optional<result>::value, "F must return an optional");
713 
714 			return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt);
715 		}
716 
717 		/// \group and_then
718 		/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
719 		template <class F>
and_then(F && f) const720 		constexpr auto and_then(F&& f) const& {
721 			using result = detail::invoke_result_t<F, const T&>;
722 			static_assert(detail::is_optional<result>::value, "F must return an optional");
723 
724 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
725 		}
726 
727 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
728 		/// \group and_then
729 		/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
730 		template <class F>
and_then(F && f) const731 		constexpr auto and_then(F&& f) const&& {
732 			using result = detail::invoke_result_t<F, const T&&>;
733 			static_assert(detail::is_optional<result>::value, "F must return an optional");
734 
735 			return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt);
736 		}
737 #endif
738 #else
739 		/// \group and_then
740 		/// Carries out some operation which returns an optional on the stored
741 		/// object if there is one. \requires `std::invoke(std::forward<F>(f),
742 		/// value())` returns a `std::optional<U>` for some `U`.
743 		/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
744 		/// value())`. Returns a `std::optional<U>`. The return value is empty if
745 		/// `*this` is empty, otherwise the return value of
746 		/// `std::invoke(std::forward<F>(f), value())` is returned.
747 		/// \group and_then
748 		/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
749 		template <class F>
750 		SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&> and_then(F&& f) & {
751 			using result = detail::invoke_result_t<F, T&>;
752 			static_assert(detail::is_optional<result>::value, "F must return an optional");
753 
754 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
755 		}
756 
757 		/// \group and_then
758 		/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
759 		template <class F>
760 		SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&&> and_then(F&& f) && {
761 			using result = detail::invoke_result_t<F, T&&>;
762 			static_assert(detail::is_optional<result>::value, "F must return an optional");
763 
764 			return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt);
765 		}
766 
767 		/// \group and_then
768 		/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
769 		template <class F>
770 		constexpr detail::invoke_result_t<F, const T&> and_then(F&& f) const& {
771 			using result = detail::invoke_result_t<F, const T&>;
772 			static_assert(detail::is_optional<result>::value, "F must return an optional");
773 
774 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
775 		}
776 
777 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
778 		/// \group and_then
779 		/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
780 		template <class F>
781 		constexpr detail::invoke_result_t<F, const T&&> and_then(F&& f) const&& {
782 			using result = detail::invoke_result_t<F, const T&&>;
783 			static_assert(detail::is_optional<result>::value, "F must return an optional");
784 
785 			return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt);
786 		}
787 #endif
788 #endif
789 
790 #if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55)
791 		/// \brief Carries out some operation on the stored object if there is one.
792 		/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
793 		/// value())`. Returns a `std::optional<U>`. The return value is empty if
794 		/// `*this` is empty, otherwise an `optional<U>` is constructed from the
795 		/// return value of `std::invoke(std::forward<F>(f), value())` and is
796 		/// returned.
797 		///
798 		/// \group map
799 		/// \synopsis template <class F> constexpr auto map(F &&f) &;
800 		template <class F>
map(F && f)801 		SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) & {
802 			return optional_map_impl(*this, std::forward<F>(f));
803 		}
804 
805 		/// \group map
806 		/// \synopsis template <class F> constexpr auto map(F &&f) &&;
807 		template <class F>
map(F && f)808 		SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) && {
809 			return optional_map_impl(std::move(*this), std::forward<F>(f));
810 		}
811 
812 		/// \group map
813 		/// \synopsis template <class F> constexpr auto map(F &&f) const&;
814 		template <class F>
map(F && f) const815 		constexpr auto map(F&& f) const& {
816 			return optional_map_impl(*this, std::forward<F>(f));
817 		}
818 
819 		/// \group map
820 		/// \synopsis template <class F> constexpr auto map(F &&f) const&&;
821 		template <class F>
map(F && f) const822 		constexpr auto map(F&& f) const&& {
823 			return optional_map_impl(std::move(*this), std::forward<F>(f));
824 		}
825 #else
826 		/// \brief Carries out some operation on the stored object if there is one.
827 		/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
828 		/// value())`. Returns a `std::optional<U>`. The return value is empty if
829 		/// `*this` is empty, otherwise an `optional<U>` is constructed from the
830 		/// return value of `std::invoke(std::forward<F>(f), value())` and is
831 		/// returned.
832 		///
833 		/// \group map
834 		/// \synopsis template <class F> auto map(F &&f) &;
835 		template <class F>
optional_map_impl(std::declval<optional &> (),std::declval<F &&> ())836 		SOL_TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&>(), std::declval<F&&>())) map(F&& f) & {
837 			return optional_map_impl(*this, std::forward<F>(f));
838 		}
839 
840 		/// \group map
841 		/// \synopsis template <class F> auto map(F &&f) &&;
842 		template <class F>
optional_map_impl(std::declval<optional &&> (),std::declval<F &&> ())843 		SOL_TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&&>(), std::declval<F&&>())) map(F&& f) && {
844 			return optional_map_impl(std::move(*this), std::forward<F>(f));
845 		}
846 
847 		/// \group map
848 		/// \synopsis template <class F> auto map(F &&f) const&;
849 		template <class F>
optional_map_impl(std::declval<const optional &> (),std::declval<F &&> ())850 		constexpr decltype(optional_map_impl(std::declval<const optional&>(), std::declval<F&&>())) map(F&& f) const& {
851 			return optional_map_impl(*this, std::forward<F>(f));
852 		}
853 
854 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
855 		/// \group map
856 		/// \synopsis template <class F> auto map(F &&f) const&&;
857 		template <class F>
optional_map_impl(std::declval<const optional &&> (),std::declval<F &&> ())858 		constexpr decltype(optional_map_impl(std::declval<const optional&&>(), std::declval<F&&>())) map(F&& f) const&& {
859 			return optional_map_impl(std::move(*this), std::forward<F>(f));
860 		}
861 #endif
862 #endif
863 
864 		/// \brief Calls `f` if the optional is empty
865 		/// \requires `std::invoke_result_t<F>` must be void or convertible to
866 		/// `optional<T>`.
867 		/// \effects If `*this` has a value, returns `*this`.
868 		/// Otherwise, if `f` returns `void`, calls `std::forward<F>(f)` and returns
869 		/// `std::nullopt`. Otherwise, returns `std::forward<F>(f)()`.
870 		///
871 		/// \group or_else
872 		/// \synopsis template <class F> optional<T> or_else (F &&f) &;
873 		template <class F, detail::enable_if_ret_void<F>* = nullptr>
or_else(F && f)874 		optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & {
875 			if (has_value())
876 				return *this;
877 
878 			std::forward<F>(f)();
879 			return nullopt;
880 		}
881 
882 		/// \exclude
883 		template <class F, detail::disable_if_ret_void<F>* = nullptr>
or_else(F && f)884 		optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & {
885 			return has_value() ? *this : std::forward<F>(f)();
886 		}
887 
888 		/// \group or_else
889 		/// \synopsis template <class F> optional<T> or_else (F &&f) &&;
890 		template <class F, detail::enable_if_ret_void<F>* = nullptr>
or_else(F && f)891 		optional<T> or_else(F&& f) && {
892 			if (has_value())
893 				return std::move(*this);
894 
895 			std::forward<F>(f)();
896 			return nullopt;
897 		}
898 
899 		/// \exclude
900 		template <class F, detail::disable_if_ret_void<F>* = nullptr>
or_else(F && f)901 		optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) && {
902 			return has_value() ? std::move(*this) : std::forward<F>(f)();
903 		}
904 
905 		/// \group or_else
906 		/// \synopsis template <class F> optional<T> or_else (F &&f) const &;
907 		template <class F, detail::enable_if_ret_void<F>* = nullptr>
or_else(F && f) const908 		optional<T> or_else(F&& f) const& {
909 			if (has_value())
910 				return *this;
911 
912 			std::forward<F>(f)();
913 			return nullopt;
914 		}
915 
916 		/// \exclude
917 		template <class F, detail::disable_if_ret_void<F>* = nullptr>
or_else(F && f) const918 		optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) const& {
919 			return has_value() ? *this : std::forward<F>(f)();
920 		}
921 
922 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
923 		/// \exclude
924 		template <class F, detail::enable_if_ret_void<F>* = nullptr>
or_else(F && f) const925 		optional<T> or_else(F&& f) const&& {
926 			if (has_value())
927 				return std::move(*this);
928 
929 			std::forward<F>(f)();
930 			return nullopt;
931 		}
932 
933 		/// \exclude
934 		template <class F, detail::disable_if_ret_void<F>* = nullptr>
or_else(F && f) const935 		optional<T> or_else(F&& f) const&& {
936 			return has_value() ? std::move(*this) : std::forward<F>(f)();
937 		}
938 #endif
939 
940 		/// \brief Maps the stored value with `f` if there is one, otherwise returns
941 		/// `u`.
942 		///
943 		/// \details If there is a value stored, then `f` is called with `**this`
944 		/// and the value is returned. Otherwise `u` is returned.
945 		///
946 		/// \group map_or
947 		template <class F, class U>
map_or(F && f,U && u)948 		U map_or(F&& f, U&& u) & {
949 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u);
950 		}
951 
952 		/// \group map_or
953 		template <class F, class U>
map_or(F && f,U && u)954 		U map_or(F&& f, U&& u) && {
955 			return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u);
956 		}
957 
958 		/// \group map_or
959 		template <class F, class U>
map_or(F && f,U && u) const960 		U map_or(F&& f, U&& u) const& {
961 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u);
962 		}
963 
964 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
965 		/// \group map_or
966 		template <class F, class U>
map_or(F && f,U && u) const967 		U map_or(F&& f, U&& u) const&& {
968 			return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u);
969 		}
970 #endif
971 
972 		/// \brief Maps the stored value with `f` if there is one, otherwise calls
973 		/// `u` and returns the result.
974 		///
975 		/// \details If there is a value stored, then `f` is
976 		/// called with `**this` and the value is returned. Otherwise
977 		/// `std::forward<U>(u)()` is returned.
978 		///
979 		/// \group map_or_else
980 		/// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u) &;
981 		template <class F, class U>
map_or_else(F && f,U && u)982 		detail::invoke_result_t<U> map_or_else(F&& f, U&& u) & {
983 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)();
984 		}
985 
986 		/// \group map_or_else
987 		/// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u)
988 		/// &&;
989 		template <class F, class U>
map_or_else(F && f,U && u)990 		detail::invoke_result_t<U> map_or_else(F&& f, U&& u) && {
991 			return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)();
992 		}
993 
994 		/// \group map_or_else
995 		/// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u)
996 		/// const &;
997 		template <class F, class U>
map_or_else(F && f,U && u) const998 		detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const& {
999 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)();
1000 		}
1001 
1002 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
1003 		/// \group map_or_else
1004 		/// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u)
1005 		/// const &&;
1006 		template <class F, class U>
map_or_else(F && f,U && u) const1007 		detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const&& {
1008 			return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)();
1009 		}
1010 #endif
1011 
1012 		/// \returns `u` if `*this` has a value, otherwise an empty optional.
1013 		template <class U>
conjunction(U && u) const1014 		constexpr optional<typename std::decay<U>::type> conjunction(U&& u) const {
1015 			using result = optional<detail::decay_t<U>>;
1016 			return has_value() ? result { u } : result { nullopt };
1017 		}
1018 
1019 		/// \returns `rhs` if `*this` is empty, otherwise the current value.
1020 		/// \group disjunction
disjunction(const optional & rhs)1021 		SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) & {
1022 			return has_value() ? *this : rhs;
1023 		}
1024 
1025 		/// \group disjunction
disjunction(const optional & rhs) const1026 		constexpr optional disjunction(const optional& rhs) const& {
1027 			return has_value() ? *this : rhs;
1028 		}
1029 
1030 		/// \group disjunction
disjunction(const optional & rhs)1031 		SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) && {
1032 			return has_value() ? std::move(*this) : rhs;
1033 		}
1034 
1035 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
1036 		/// \group disjunction
disjunction(const optional & rhs) const1037 		constexpr optional disjunction(const optional& rhs) const&& {
1038 			return has_value() ? std::move(*this) : rhs;
1039 		}
1040 #endif
1041 
1042 		/// \group disjunction
disjunction(optional && rhs)1043 		SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) & {
1044 			return has_value() ? *this : std::move(rhs);
1045 		}
1046 
1047 		/// \group disjunction
disjunction(optional && rhs) const1048 		constexpr optional disjunction(optional&& rhs) const& {
1049 			return has_value() ? *this : std::move(rhs);
1050 		}
1051 
1052 		/// \group disjunction
disjunction(optional && rhs)1053 		SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) && {
1054 			return has_value() ? std::move(*this) : std::move(rhs);
1055 		}
1056 
1057 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
1058 		/// \group disjunction
disjunction(optional && rhs) const1059 		constexpr optional disjunction(optional&& rhs) const&& {
1060 			return has_value() ? std::move(*this) : std::move(rhs);
1061 		}
1062 #endif
1063 
1064 		/// Takes the value out of the optional, leaving it empty
1065 		/// \group take
take()1066 		optional take() & {
1067 			optional ret = *this;
1068 			reset();
1069 			return ret;
1070 		}
1071 
1072 		/// \group take
take() const1073 		optional take() const& {
1074 			optional ret = *this;
1075 			reset();
1076 			return ret;
1077 		}
1078 
1079 		/// \group take
take()1080 		optional take() && {
1081 			optional ret = std::move(*this);
1082 			reset();
1083 			return ret;
1084 		}
1085 
1086 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
1087 		/// \group take
take() const1088 		optional take() const&& {
1089 			optional ret = std::move(*this);
1090 			reset();
1091 			return ret;
1092 		}
1093 #endif
1094 
1095 		using value_type = T;
1096 
1097 		/// Constructs an optional that does not contain a value.
1098 		/// \group ctor_empty
1099 		constexpr optional() noexcept = default;
1100 
1101 		/// \group ctor_empty
optional(nullopt_t)1102 		constexpr optional(nullopt_t) noexcept {
1103 		}
1104 
1105 		/// Copy constructor
1106 		///
1107 		/// If `rhs` contains a value, the stored value is direct-initialized with
1108 		/// it. Otherwise, the constructed optional is empty.
1109 		SOL_TL_OPTIONAL_11_CONSTEXPR optional(const optional& rhs) = default;
1110 
1111 		/// Move constructor
1112 		///
1113 		/// If `rhs` contains a value, the stored value is direct-initialized with
1114 		/// it. Otherwise, the constructed optional is empty.
1115 		SOL_TL_OPTIONAL_11_CONSTEXPR optional(optional&& rhs) = default;
1116 
1117 		/// Constructs the stored value in-place using the given arguments.
1118 		/// \group in_place
1119 		/// \synopsis template <class... Args> constexpr explicit optional(in_place_t, Args&&... args);
1120 		template <class... Args>
optional(detail::enable_if_t<std::is_constructible<T,Args...>::value,in_place_t>,Args &&...args)1121 		constexpr explicit optional(detail::enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>, Args&&... args)
1122 		: base(in_place, std::forward<Args>(args)...) {
1123 		}
1124 
1125 		/// \group in_place
1126 		/// \synopsis template <class U, class... Args>\nconstexpr explicit optional(in_place_t, std::initializer_list<U>&, Args&&... args);
1127 		template <class U, class... Args>
optional(detail::enable_if_t<std::is_constructible<T,std::initializer_list<U> &,Args &&...>::value,in_place_t>,std::initializer_list<U> il,Args &&...args)1128 		SOL_TL_OPTIONAL_11_CONSTEXPR explicit optional(detail::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, in_place_t>,
1129 		     std::initializer_list<U> il, Args&&... args) {
1130 			this->construct(il, std::forward<Args>(args)...);
1131 		}
1132 
1133 #if 0 // SOL_MODIFICATION
1134       /// Constructs the stored value with `u`.
1135       /// \synopsis template <class U=T> constexpr optional(U &&u);
1136 		template <class U = T, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr, detail::enable_forward_value<T, U>* = nullptr>
1137 		constexpr optional(U&& u) : base(in_place, std::forward<U>(u)) {
1138 		}
1139 
1140 		/// \exclude
1141 		template <class U = T, detail::enable_if_t<!std::is_convertible<U&&, T>::value>* = nullptr, detail::enable_forward_value<T, U>* = nullptr>
1142 		constexpr explicit optional(U&& u) : base(in_place, std::forward<U>(u)) {
1143 		}
1144 #else
1145 		/// Constructs the stored value with `u`.
1146 		/// \synopsis template <class U=T> constexpr optional(U &&u);
optional(T && u)1147 		constexpr optional(T&& u) : base(in_place, std::move(u)) {
1148 		}
1149 
1150 		/// \exclude
optional(const T & u)1151 		constexpr optional(const T& u) : base(in_place, u) {
1152 		}
1153 #endif // sol3 modification
1154 
1155 		/// Converting copy constructor.
1156 		/// \synopsis template <class U> optional(const optional<U> &rhs);
1157 		template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<std::is_convertible<const U&, T>::value>* = nullptr>
optional(const optional<U> & rhs)1158 		optional(const optional<U>& rhs) {
1159 			if (rhs.has_value()) {
1160 				this->construct(*rhs);
1161 			}
1162 		}
1163 
1164 		/// \exclude
1165 		template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<!std::is_convertible<const U&, T>::value>* = nullptr>
optional(const optional<U> & rhs)1166 		explicit optional(const optional<U>& rhs) {
1167 			if (rhs.has_value()) {
1168 				this->construct(*rhs);
1169 			}
1170 		}
1171 
1172 		/// Converting move constructor.
1173 		/// \synopsis template <class U> optional(optional<U> &&rhs);
1174 		template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr>
optional(optional<U> && rhs)1175 		optional(optional<U>&& rhs) {
1176 			if (rhs.has_value()) {
1177 				this->construct(std::move(*rhs));
1178 			}
1179 		}
1180 
1181 		/// \exclude
1182 		template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<!std::is_convertible<U&&, T>::value>* = nullptr>
optional(optional<U> && rhs)1183 		explicit optional(optional<U>&& rhs) {
1184 			this->construct(std::move(*rhs));
1185 		}
1186 
1187 		/// Destroys the stored value if there is one.
1188 		~optional() = default;
1189 
1190 		/// Assignment to empty.
1191 		///
1192 		/// Destroys the current value if there is one.
operator =(nullopt_t)1193 		optional& operator=(nullopt_t) noexcept {
1194 			if (has_value()) {
1195 				this->m_value.~T();
1196 				this->m_has_value = false;
1197 			}
1198 
1199 			return *this;
1200 		}
1201 
1202 		/// Copy assignment.
1203 		///
1204 		/// Copies the value from `rhs` if there is one. Otherwise resets the stored
1205 		/// value in `*this`.
1206 		optional& operator=(const optional& rhs) = default;
1207 
1208 		/// Move assignment.
1209 		///
1210 		/// Moves the value from `rhs` if there is one. Otherwise resets the stored
1211 		/// value in `*this`.
1212 		optional& operator=(optional&& rhs) = default;
1213 
1214 		/// Assigns the stored value from `u`, destroying the old value if there was
1215 		/// one.
1216 		/// \synopsis optional &operator=(U &&u);
1217 		template <class U = T, detail::enable_assign_forward<T, U>* = nullptr>
operator =(U && u)1218 		optional& operator=(U&& u) {
1219 			if (has_value()) {
1220 				this->m_value = std::forward<U>(u);
1221 			}
1222 			else {
1223 				this->construct(std::forward<U>(u));
1224 			}
1225 
1226 			return *this;
1227 		}
1228 
1229 		/// Converting copy assignment operator.
1230 		///
1231 		/// Copies the value from `rhs` if there is one. Otherwise resets the stored
1232 		/// value in `*this`.
1233 		/// \synopsis optional &operator=(const optional<U> & rhs);
1234 		template <class U, detail::enable_assign_from_other<T, U, const U&>* = nullptr>
operator =(const optional<U> & rhs)1235 		optional& operator=(const optional<U>& rhs) {
1236 			if (has_value()) {
1237 				if (rhs.has_value()) {
1238 					this->m_value = *rhs;
1239 				}
1240 				else {
1241 					this->hard_reset();
1242 				}
1243 			}
1244 
1245 			if (rhs.has_value()) {
1246 				this->construct(*rhs);
1247 			}
1248 
1249 			return *this;
1250 		}
1251 
1252 		// TODO check exception guarantee
1253 		/// Converting move assignment operator.
1254 		///
1255 		/// Moves the value from `rhs` if there is one. Otherwise resets the stored
1256 		/// value in `*this`.
1257 		/// \synopsis optional &operator=(optional<U> && rhs);
1258 		template <class U, detail::enable_assign_from_other<T, U, U>* = nullptr>
operator =(optional<U> && rhs)1259 		optional& operator=(optional<U>&& rhs) {
1260 			if (has_value()) {
1261 				if (rhs.has_value()) {
1262 					this->m_value = std::move(*rhs);
1263 				}
1264 				else {
1265 					this->hard_reset();
1266 				}
1267 			}
1268 
1269 			if (rhs.has_value()) {
1270 				this->construct(std::move(*rhs));
1271 			}
1272 
1273 			return *this;
1274 		}
1275 
1276 		/// Constructs the value in-place, destroying the current one if there is
1277 		/// one.
1278 		/// \group emplace
1279 		template <class... Args>
emplace(Args &&...args)1280 		T& emplace(Args&&... args) {
1281 			static_assert(std::is_constructible<T, Args&&...>::value, "T must be constructible with Args");
1282 
1283 			*this = nullopt;
1284 			this->construct(std::forward<Args>(args)...);
1285 			return value();
1286 		}
1287 
1288 		/// \group emplace
1289 		/// \synopsis template <class U, class... Args>\nT& emplace(std::initializer_list<U> il, Args &&... args);
1290 		template <class U, class... Args>
emplace(std::initializer_list<U> il,Args &&...args)1291 		detail::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, T&> emplace(std::initializer_list<U> il, Args&&... args) {
1292 			*this = nullopt;
1293 			this->construct(il, std::forward<Args>(args)...);
1294 			return value();
1295 		}
1296 
1297 		/// Swaps this optional with the other.
1298 		///
1299 		/// If neither optionals have a value, nothing happens.
1300 		/// If both have a value, the values are swapped.
1301 		/// If one has a value, it is moved to the other and the movee is left
1302 		/// valueless.
swap(optional & rhs)1303 		void swap(optional& rhs) noexcept(std::is_nothrow_move_constructible<T>::value&& detail::is_nothrow_swappable<T>::value) {
1304 			if (has_value()) {
1305 				if (rhs.has_value()) {
1306 					using std::swap;
1307 					swap(**this, *rhs);
1308 				}
1309 				else {
1310 					new (std::addressof(rhs.m_value)) T(std::move(this->m_value));
1311 					this->m_value.T::~T();
1312 				}
1313 			}
1314 			else if (rhs.has_value()) {
1315 				new (std::addressof(this->m_value)) T(std::move(rhs.m_value));
1316 				rhs.m_value.T::~T();
1317 			}
1318 		}
1319 
1320 		/// \returns a pointer to the stored value
1321 		/// \requires a value is stored
1322 		/// \group pointer
1323 		/// \synopsis constexpr const T *operator->() const;
operator ->() const1324 		constexpr const T* operator->() const {
1325 			return std::addressof(this->m_value);
1326 		}
1327 
1328 		/// \group pointer
1329 		/// \synopsis constexpr T *operator->();
operator ->()1330 		SOL_TL_OPTIONAL_11_CONSTEXPR T* operator->() {
1331 			return std::addressof(this->m_value);
1332 		}
1333 
1334 		/// \returns the stored value
1335 		/// \requires a value is stored
1336 		/// \group deref
1337 		/// \synopsis constexpr T &operator*();
operator *()1338 		SOL_TL_OPTIONAL_11_CONSTEXPR T& operator*() & {
1339 			return this->m_value;
1340 		}
1341 
1342 		/// \group deref
1343 		/// \synopsis constexpr const T &operator*() const;
operator *() const1344 		constexpr const T& operator*() const& {
1345 			return this->m_value;
1346 		}
1347 
1348 		/// \exclude
operator *()1349 		SOL_TL_OPTIONAL_11_CONSTEXPR T&& operator*() && {
1350 			return std::move(this->m_value);
1351 		}
1352 
1353 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
1354 		/// \exclude
operator *() const1355 		constexpr const T&& operator*() const&& {
1356 			return std::move(this->m_value);
1357 		}
1358 #endif
1359 
1360 		/// \returns whether or not the optional has a value
1361 		/// \group has_value
has_value() const1362 		constexpr bool has_value() const noexcept {
1363 			return this->m_has_value;
1364 		}
1365 
1366 		/// \group has_value
operator bool() const1367 		constexpr explicit operator bool() const noexcept {
1368 			return this->m_has_value;
1369 		}
1370 
1371 		/// \returns the contained value if there is one, otherwise throws
1372 		/// [bad_optional_access]
1373 		/// \group value
1374 		/// \synopsis constexpr T &value();
value()1375 		SOL_TL_OPTIONAL_11_CONSTEXPR T& value() & {
1376 			if (has_value())
1377 				return this->m_value;
1378 #if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
1379 			std::abort();
1380 #else
1381 			throw bad_optional_access();
1382 #endif // No exceptions allowed
1383 		}
1384 		/// \group value
1385 		/// \synopsis constexpr const T &value() const;
value() const1386 		SOL_TL_OPTIONAL_11_CONSTEXPR const T& value() const& {
1387 			if (has_value())
1388 				return this->m_value;
1389 #if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
1390 			std::abort();
1391 #else
1392 			throw bad_optional_access();
1393 #endif // No exceptions allowed
1394 		}
1395 		/// \exclude
value()1396 		SOL_TL_OPTIONAL_11_CONSTEXPR T&& value() && {
1397 			if (has_value())
1398 				return std::move(this->m_value);
1399 #if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
1400 			std::abort();
1401 #else
1402 			throw bad_optional_access();
1403 #endif // No exceptions allowed
1404 		}
1405 
1406 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
1407 		/// \exclude
value() const1408 		SOL_TL_OPTIONAL_11_CONSTEXPR const T&& value() const&& {
1409 			if (has_value())
1410 				return std::move(this->m_value);
1411 #if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
1412 			std::abort();
1413 #else
1414 			throw bad_optional_access();
1415 #endif // No exceptions allowed
1416 		}
1417 #endif
1418 
1419 		/// \returns the stored value if there is one, otherwise returns `u`
1420 		/// \group value_or
1421 		template <class U>
value_or(U && u) const1422 		constexpr T value_or(U&& u) const& {
1423 			static_assert(std::is_copy_constructible<T>::value && std::is_convertible<U&&, T>::value, "T must be copy constructible and convertible from U");
1424 			return has_value() ? **this : static_cast<T>(std::forward<U>(u));
1425 		}
1426 
1427 		/// \group value_or
1428 		template <class U>
value_or(U && u)1429 		SOL_TL_OPTIONAL_11_CONSTEXPR T value_or(U&& u) && {
1430 			static_assert(std::is_move_constructible<T>::value && std::is_convertible<U&&, T>::value, "T must be move constructible and convertible from U");
1431 			return has_value() ? **this : static_cast<T>(std::forward<U>(u));
1432 		}
1433 
1434 		/// Destroys the stored value if one exists, making the optional empty
reset()1435 		void reset() noexcept {
1436 			if (has_value()) {
1437 				this->m_value.~T();
1438 				this->m_has_value = false;
1439 			}
1440 		}
1441 	}; // namespace sol
1442 
1443 	/// \group relop
1444 	/// \brief Compares two optional objects
1445 	/// \details If both optionals contain a value, they are compared with `T`s
1446 	/// relational operators. Otherwise `lhs` and `rhs` are equal only if they are
1447 	/// both empty, and `lhs` is less than `rhs` only if `rhs` is empty and `lhs`
1448 	/// is not.
1449 	template <class T, class U>
operator ==(const optional<T> & lhs,const optional<U> & rhs)1450 	inline constexpr bool operator==(const optional<T>& lhs, const optional<U>& rhs) {
1451 		return lhs.has_value() == rhs.has_value() && (!lhs.has_value() || *lhs == *rhs);
1452 	}
1453 	/// \group relop
1454 	template <class T, class U>
operator !=(const optional<T> & lhs,const optional<U> & rhs)1455 	inline constexpr bool operator!=(const optional<T>& lhs, const optional<U>& rhs) {
1456 		return lhs.has_value() != rhs.has_value() || (lhs.has_value() && *lhs != *rhs);
1457 	}
1458 	/// \group relop
1459 	template <class T, class U>
operator <(const optional<T> & lhs,const optional<U> & rhs)1460 	inline constexpr bool operator<(const optional<T>& lhs, const optional<U>& rhs) {
1461 		return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs);
1462 	}
1463 	/// \group relop
1464 	template <class T, class U>
operator >(const optional<T> & lhs,const optional<U> & rhs)1465 	inline constexpr bool operator>(const optional<T>& lhs, const optional<U>& rhs) {
1466 		return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs);
1467 	}
1468 	/// \group relop
1469 	template <class T, class U>
operator <=(const optional<T> & lhs,const optional<U> & rhs)1470 	inline constexpr bool operator<=(const optional<T>& lhs, const optional<U>& rhs) {
1471 		return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs);
1472 	}
1473 	/// \group relop
1474 	template <class T, class U>
operator >=(const optional<T> & lhs,const optional<U> & rhs)1475 	inline constexpr bool operator>=(const optional<T>& lhs, const optional<U>& rhs) {
1476 		return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs);
1477 	}
1478 
1479 	/// \group relop_nullopt
1480 	/// \brief Compares an optional to a `nullopt`
1481 	/// \details Equivalent to comparing the optional to an empty optional
1482 	template <class T>
operator ==(const optional<T> & lhs,nullopt_t)1483 	inline constexpr bool operator==(const optional<T>& lhs, nullopt_t) noexcept {
1484 		return !lhs.has_value();
1485 	}
1486 	/// \group relop_nullopt
1487 	template <class T>
operator ==(nullopt_t,const optional<T> & rhs)1488 	inline constexpr bool operator==(nullopt_t, const optional<T>& rhs) noexcept {
1489 		return !rhs.has_value();
1490 	}
1491 	/// \group relop_nullopt
1492 	template <class T>
operator !=(const optional<T> & lhs,nullopt_t)1493 	inline constexpr bool operator!=(const optional<T>& lhs, nullopt_t) noexcept {
1494 		return lhs.has_value();
1495 	}
1496 	/// \group relop_nullopt
1497 	template <class T>
operator !=(nullopt_t,const optional<T> & rhs)1498 	inline constexpr bool operator!=(nullopt_t, const optional<T>& rhs) noexcept {
1499 		return rhs.has_value();
1500 	}
1501 	/// \group relop_nullopt
1502 	template <class T>
operator <(const optional<T> &,nullopt_t)1503 	inline constexpr bool operator<(const optional<T>&, nullopt_t) noexcept {
1504 		return false;
1505 	}
1506 	/// \group relop_nullopt
1507 	template <class T>
operator <(nullopt_t,const optional<T> & rhs)1508 	inline constexpr bool operator<(nullopt_t, const optional<T>& rhs) noexcept {
1509 		return rhs.has_value();
1510 	}
1511 	/// \group relop_nullopt
1512 	template <class T>
operator <=(const optional<T> & lhs,nullopt_t)1513 	inline constexpr bool operator<=(const optional<T>& lhs, nullopt_t) noexcept {
1514 		return !lhs.has_value();
1515 	}
1516 	/// \group relop_nullopt
1517 	template <class T>
operator <=(nullopt_t,const optional<T> &)1518 	inline constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept {
1519 		return true;
1520 	}
1521 	/// \group relop_nullopt
1522 	template <class T>
operator >(const optional<T> & lhs,nullopt_t)1523 	inline constexpr bool operator>(const optional<T>& lhs, nullopt_t) noexcept {
1524 		return lhs.has_value();
1525 	}
1526 	/// \group relop_nullopt
1527 	template <class T>
operator >(nullopt_t,const optional<T> &)1528 	inline constexpr bool operator>(nullopt_t, const optional<T>&) noexcept {
1529 		return false;
1530 	}
1531 	/// \group relop_nullopt
1532 	template <class T>
operator >=(const optional<T> &,nullopt_t)1533 	inline constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept {
1534 		return true;
1535 	}
1536 	/// \group relop_nullopt
1537 	template <class T>
operator >=(nullopt_t,const optional<T> & rhs)1538 	inline constexpr bool operator>=(nullopt_t, const optional<T>& rhs) noexcept {
1539 		return !rhs.has_value();
1540 	}
1541 
1542 	/// \group relop_t
1543 	/// \brief Compares the optional with a value.
1544 	/// \details If the optional has a value, it is compared with the other value
1545 	/// using `T`s relational operators. Otherwise, the optional is considered
1546 	/// less than the value.
1547 	template <class T, class U>
operator ==(const optional<T> & lhs,const U & rhs)1548 	inline constexpr bool operator==(const optional<T>& lhs, const U& rhs) {
1549 		return lhs.has_value() ? *lhs == rhs : false;
1550 	}
1551 	/// \group relop_t
1552 	template <class T, class U>
operator ==(const U & lhs,const optional<T> & rhs)1553 	inline constexpr bool operator==(const U& lhs, const optional<T>& rhs) {
1554 		return rhs.has_value() ? lhs == *rhs : false;
1555 	}
1556 	/// \group relop_t
1557 	template <class T, class U>
operator !=(const optional<T> & lhs,const U & rhs)1558 	inline constexpr bool operator!=(const optional<T>& lhs, const U& rhs) {
1559 		return lhs.has_value() ? *lhs != rhs : true;
1560 	}
1561 	/// \group relop_t
1562 	template <class T, class U>
operator !=(const U & lhs,const optional<T> & rhs)1563 	inline constexpr bool operator!=(const U& lhs, const optional<T>& rhs) {
1564 		return rhs.has_value() ? lhs != *rhs : true;
1565 	}
1566 	/// \group relop_t
1567 	template <class T, class U>
operator <(const optional<T> & lhs,const U & rhs)1568 	inline constexpr bool operator<(const optional<T>& lhs, const U& rhs) {
1569 		return lhs.has_value() ? *lhs < rhs : true;
1570 	}
1571 	/// \group relop_t
1572 	template <class T, class U>
operator <(const U & lhs,const optional<T> & rhs)1573 	inline constexpr bool operator<(const U& lhs, const optional<T>& rhs) {
1574 		return rhs.has_value() ? lhs < *rhs : false;
1575 	}
1576 	/// \group relop_t
1577 	template <class T, class U>
operator <=(const optional<T> & lhs,const U & rhs)1578 	inline constexpr bool operator<=(const optional<T>& lhs, const U& rhs) {
1579 		return lhs.has_value() ? *lhs <= rhs : true;
1580 	}
1581 	/// \group relop_t
1582 	template <class T, class U>
operator <=(const U & lhs,const optional<T> & rhs)1583 	inline constexpr bool operator<=(const U& lhs, const optional<T>& rhs) {
1584 		return rhs.has_value() ? lhs <= *rhs : false;
1585 	}
1586 	/// \group relop_t
1587 	template <class T, class U>
operator >(const optional<T> & lhs,const U & rhs)1588 	inline constexpr bool operator>(const optional<T>& lhs, const U& rhs) {
1589 		return lhs.has_value() ? *lhs > rhs : false;
1590 	}
1591 	/// \group relop_t
1592 	template <class T, class U>
operator >(const U & lhs,const optional<T> & rhs)1593 	inline constexpr bool operator>(const U& lhs, const optional<T>& rhs) {
1594 		return rhs.has_value() ? lhs > *rhs : true;
1595 	}
1596 	/// \group relop_t
1597 	template <class T, class U>
operator >=(const optional<T> & lhs,const U & rhs)1598 	inline constexpr bool operator>=(const optional<T>& lhs, const U& rhs) {
1599 		return lhs.has_value() ? *lhs >= rhs : false;
1600 	}
1601 	/// \group relop_t
1602 	template <class T, class U>
operator >=(const U & lhs,const optional<T> & rhs)1603 	inline constexpr bool operator>=(const U& lhs, const optional<T>& rhs) {
1604 		return rhs.has_value() ? lhs >= *rhs : true;
1605 	}
1606 
1607 	/// \synopsis template <class T>\nvoid swap(optional<T> &lhs, optional<T> &rhs);
1608 	template <class T, detail::enable_if_t<std::is_move_constructible<T>::value>* = nullptr, detail::enable_if_t<detail::is_swappable<T>::value>* = nullptr>
swap(optional<T> & lhs,optional<T> & rhs)1609 	void swap(optional<T>& lhs, optional<T>& rhs) noexcept(noexcept(lhs.swap(rhs))) {
1610 		return lhs.swap(rhs);
1611 	}
1612 
1613 	namespace detail {
1614 		struct i_am_secret { };
1615 	} // namespace detail
1616 
1617 	template <class T = detail::i_am_secret, class U, class Ret = detail::conditional_t<std::is_same<T, detail::i_am_secret>::value, detail::decay_t<U>, T>>
make_optional(U && v)1618 	inline constexpr optional<Ret> make_optional(U&& v) {
1619 		return optional<Ret>(std::forward<U>(v));
1620 	}
1621 
1622 	template <class T, class... Args>
make_optional(Args &&...args)1623 	inline constexpr optional<T> make_optional(Args&&... args) {
1624 		return optional<T>(in_place, std::forward<Args>(args)...);
1625 	}
1626 	template <class T, class U, class... Args>
make_optional(std::initializer_list<U> il,Args &&...args)1627 	inline constexpr optional<T> make_optional(std::initializer_list<U> il, Args&&... args) {
1628 		return optional<T>(in_place, il, std::forward<Args>(args)...);
1629 	}
1630 
1631 #if __cplusplus >= 201703L
1632 	template <class T>
1633 	optional(T) -> optional<T>;
1634 #endif
1635 
1636 	/// \exclude
1637 	namespace detail {
1638 #ifdef SOL_TL_OPTIONAL_CXX14
1639 		template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())),
1640 		     detail::enable_if_t<!std::is_void<Ret>::value>* = nullptr>
optional_map_impl(Opt && opt,F && f)1641 		constexpr auto optional_map_impl(Opt&& opt, F&& f) {
1642 			return opt.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt)) : optional<Ret>(nullopt);
1643 		}
1644 
1645 		template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())),
1646 		     detail::enable_if_t<std::is_void<Ret>::value>* = nullptr>
optional_map_impl(Opt && opt,F && f)1647 		auto optional_map_impl(Opt&& opt, F&& f) {
1648 			if (opt.has_value()) {
1649 				detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
1650 				return make_optional(monostate {});
1651 			}
1652 
1653 			return optional<monostate>(nullopt);
1654 		}
1655 #else
1656 		template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())),
1657 		     detail::enable_if_t<!std::is_void<Ret>::value>* = nullptr>
1658 
1659 		constexpr auto optional_map_impl(Opt&& opt, F&& f) -> optional<Ret> {
1660 			return opt.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt)) : optional<Ret>(nullopt);
1661 		}
1662 
1663 		template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())),
1664 		     detail::enable_if_t<std::is_void<Ret>::value>* = nullptr>
1665 
1666 		auto optional_map_impl(Opt&& opt, F&& f) -> optional<monostate> {
1667 			if (opt.has_value()) {
1668 				detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
1669 				return monostate {};
1670 			}
1671 
1672 			return nullopt;
1673 		}
1674 #endif
1675 	} // namespace detail
1676 
1677 	/// Specialization for when `T` is a reference. `optional<T&>` acts similarly
1678 	/// to a `T*`, but provides more operations and shows intent more clearly.
1679 	///
1680 	/// *Examples*:
1681 	///
1682 	/// ```
1683 	/// int i = 42;
1684 	/// sol::optional<int&> o = i;
1685 	/// *o == 42; //true
1686 	/// i = 12;
1687 	/// *o = 12; //true
1688 	/// &*o == &i; //true
1689 	/// ```
1690 	///
1691 	/// Assignment has rebind semantics rather than assign-through semantics:
1692 	///
1693 	/// ```
1694 	/// int j = 8;
1695 	/// o = j;
1696 	///
1697 	/// &*o == &j; //true
1698 	/// ```
1699 	template <class T>
1700 	class optional<T&> {
1701 	public:
1702 // The different versions for C++14 and 11 are needed because deduced return
1703 // types are not SFINAE-safe. This provides better support for things like
1704 // generic lambdas. C.f.
1705 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
1706 #if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55)
1707 		/// \group and_then
1708 		/// Carries out some operation which returns an optional on the stored
1709 		/// object if there is one. \requires `std::invoke(std::forward<F>(f),
1710 		/// value())` returns a `std::optional<U>` for some `U`. \returns Let `U` be
1711 		/// the result of `std::invoke(std::forward<F>(f), value())`. Returns a
1712 		/// `std::optional<U>`. The return value is empty if `*this` is empty,
1713 		/// otherwise the return value of `std::invoke(std::forward<F>(f), value())`
1714 		/// is returned.
1715 		/// \group and_then
1716 		/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
1717 		template <class F>
and_then(F && f)1718 		SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) & {
1719 			using result = detail::invoke_result_t<F, T&>;
1720 			static_assert(detail::is_optional<result>::value, "F must return an optional");
1721 
1722 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
1723 		}
1724 
1725 		/// \group and_then
1726 		/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
1727 		template <class F>
and_then(F && f)1728 		SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) && {
1729 			using result = detail::invoke_result_t<F, T&>;
1730 			static_assert(detail::is_optional<result>::value, "F must return an optional");
1731 
1732 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
1733 		}
1734 
1735 		/// \group and_then
1736 		/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
1737 		template <class F>
and_then(F && f) const1738 		constexpr auto and_then(F&& f) const& {
1739 			using result = detail::invoke_result_t<F, const T&>;
1740 			static_assert(detail::is_optional<result>::value, "F must return an optional");
1741 
1742 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
1743 		}
1744 
1745 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
1746 		/// \group and_then
1747 		/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
1748 		template <class F>
and_then(F && f) const1749 		constexpr auto and_then(F&& f) const&& {
1750 			using result = detail::invoke_result_t<F, const T&>;
1751 			static_assert(detail::is_optional<result>::value, "F must return an optional");
1752 
1753 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
1754 		}
1755 #endif
1756 #else
1757 		/// \group and_then
1758 		/// Carries out some operation which returns an optional on the stored
1759 		/// object if there is one. \requires `std::invoke(std::forward<F>(f),
1760 		/// value())` returns a `std::optional<U>` for some `U`. \returns Let `U` be
1761 		/// the result of `std::invoke(std::forward<F>(f), value())`. Returns a
1762 		/// `std::optional<U>`. The return value is empty if `*this` is empty,
1763 		/// otherwise the return value of `std::invoke(std::forward<F>(f), value())`
1764 		/// is returned.
1765 		/// \group and_then
1766 		/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
1767 		template <class F>
1768 		SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&> and_then(F&& f) & {
1769 			using result = detail::invoke_result_t<F, T&>;
1770 			static_assert(detail::is_optional<result>::value, "F must return an optional");
1771 
1772 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
1773 		}
1774 
1775 		/// \group and_then
1776 		/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
1777 		template <class F>
1778 		SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&> and_then(F&& f) && {
1779 			using result = detail::invoke_result_t<F, T&>;
1780 			static_assert(detail::is_optional<result>::value, "F must return an optional");
1781 
1782 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
1783 		}
1784 
1785 		/// \group and_then
1786 		/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
1787 		template <class F>
1788 		constexpr detail::invoke_result_t<F, const T&> and_then(F&& f) const& {
1789 			using result = detail::invoke_result_t<F, const T&>;
1790 			static_assert(detail::is_optional<result>::value, "F must return an optional");
1791 
1792 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
1793 		}
1794 
1795 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
1796 		/// \group and_then
1797 		/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
1798 		template <class F>
1799 		constexpr detail::invoke_result_t<F, const T&> and_then(F&& f) const&& {
1800 			using result = detail::invoke_result_t<F, const T&>;
1801 			static_assert(detail::is_optional<result>::value, "F must return an optional");
1802 
1803 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
1804 		}
1805 #endif
1806 #endif
1807 
1808 #if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55)
1809 		/// \brief Carries out some operation on the stored object if there is one.
1810 		/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
1811 		/// value())`. Returns a `std::optional<U>`. The return value is empty if
1812 		/// `*this` is empty, otherwise an `optional<U>` is constructed from the
1813 		/// return value of `std::invoke(std::forward<F>(f), value())` and is
1814 		/// returned.
1815 		///
1816 		/// \group map
1817 		/// \synopsis template <class F> constexpr auto map(F &&f) &;
1818 		template <class F>
map(F && f)1819 		SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) & {
1820 			return detail::optional_map_impl(*this, std::forward<F>(f));
1821 		}
1822 
1823 		/// \group map
1824 		/// \synopsis template <class F> constexpr auto map(F &&f) &&;
1825 		template <class F>
map(F && f)1826 		SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) && {
1827 			return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1828 		}
1829 
1830 		/// \group map
1831 		/// \synopsis template <class F> constexpr auto map(F &&f) const&;
1832 		template <class F>
map(F && f) const1833 		constexpr auto map(F&& f) const& {
1834 			return detail::optional_map_impl(*this, std::forward<F>(f));
1835 		}
1836 
1837 		/// \group map
1838 		/// \synopsis template <class F> constexpr auto map(F &&f) const&&;
1839 		template <class F>
map(F && f) const1840 		constexpr auto map(F&& f) const&& {
1841 			return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1842 		}
1843 #else
1844 		/// \brief Carries out some operation on the stored object if there is one.
1845 		/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
1846 		/// value())`. Returns a `std::optional<U>`. The return value is empty if
1847 		/// `*this` is empty, otherwise an `optional<U>` is constructed from the
1848 		/// return value of `std::invoke(std::forward<F>(f), value())` and is
1849 		/// returned.
1850 		///
1851 		/// \group map
1852 		/// \synopsis template <class F> auto map(F &&f) &;
1853 		template <class F>
optional_map_impl(std::declval<optional &> (),std::declval<F &&> ())1854 		SOL_TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&>(), std::declval<F&&>())) map(F&& f) & {
1855 			return detail::optional_map_impl(*this, std::forward<F>(f));
1856 		}
1857 
1858 		/// \group map
1859 		/// \synopsis template <class F> auto map(F &&f) &&;
1860 		template <class F>
optional_map_impl(std::declval<optional &&> (),std::declval<F &&> ())1861 		SOL_TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&&>(), std::declval<F&&>())) map(F&& f) && {
1862 			return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1863 		}
1864 
1865 		/// \group map
1866 		/// \synopsis template <class F> auto map(F &&f) const&;
1867 		template <class F>
optional_map_impl(std::declval<const optional &> (),std::declval<F &&> ())1868 		constexpr decltype(detail::optional_map_impl(std::declval<const optional&>(), std::declval<F&&>())) map(F&& f) const& {
1869 			return detail::optional_map_impl(*this, std::forward<F>(f));
1870 		}
1871 
1872 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
1873 		/// \group map
1874 		/// \synopsis template <class F> auto map(F &&f) const&&;
1875 		template <class F>
optional_map_impl(std::declval<const optional &&> (),std::declval<F &&> ())1876 		constexpr decltype(detail::optional_map_impl(std::declval<const optional&&>(), std::declval<F&&>())) map(F&& f) const&& {
1877 			return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1878 		}
1879 #endif
1880 #endif
1881 
1882 		/// \brief Calls `f` if the optional is empty
1883 		/// \requires `std::invoke_result_t<F>` must be void or convertible to
1884 		/// `optional<T>`. \effects If `*this` has a value, returns `*this`.
1885 		/// Otherwise, if `f` returns `void`, calls `std::forward<F>(f)` and returns
1886 		/// `std::nullopt`. Otherwise, returns `std::forward<F>(f)()`.
1887 		///
1888 		/// \group or_else
1889 		/// \synopsis template <class F> optional<T> or_else (F &&f) &;
1890 		template <class F, detail::enable_if_ret_void<F>* = nullptr>
or_else(F && f)1891 		optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & {
1892 			if (has_value())
1893 				return *this;
1894 
1895 			std::forward<F>(f)();
1896 			return nullopt;
1897 		}
1898 
1899 		/// \exclude
1900 		template <class F, detail::disable_if_ret_void<F>* = nullptr>
or_else(F && f)1901 		optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & {
1902 			return has_value() ? *this : std::forward<F>(f)();
1903 		}
1904 
1905 		/// \group or_else
1906 		/// \synopsis template <class F> optional<T> or_else (F &&f) &&;
1907 		template <class F, detail::enable_if_ret_void<F>* = nullptr>
or_else(F && f)1908 		optional<T> or_else(F&& f) && {
1909 			if (has_value())
1910 				return std::move(*this);
1911 
1912 			std::forward<F>(f)();
1913 			return nullopt;
1914 		}
1915 
1916 		/// \exclude
1917 		template <class F, detail::disable_if_ret_void<F>* = nullptr>
or_else(F && f)1918 		optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) && {
1919 			return has_value() ? std::move(*this) : std::forward<F>(f)();
1920 		}
1921 
1922 		/// \group or_else
1923 		/// \synopsis template <class F> optional<T> or_else (F &&f) const &;
1924 		template <class F, detail::enable_if_ret_void<F>* = nullptr>
or_else(F && f) const1925 		optional<T> or_else(F&& f) const& {
1926 			if (has_value())
1927 				return *this;
1928 
1929 			std::forward<F>(f)();
1930 			return nullopt;
1931 		}
1932 
1933 		/// \exclude
1934 		template <class F, detail::disable_if_ret_void<F>* = nullptr>
or_else(F && f) const1935 		optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) const& {
1936 			return has_value() ? *this : std::forward<F>(f)();
1937 		}
1938 
1939 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
1940 		/// \exclude
1941 		template <class F, detail::enable_if_ret_void<F>* = nullptr>
or_else(F && f) const1942 		optional<T> or_else(F&& f) const&& {
1943 			if (has_value())
1944 				return std::move(*this);
1945 
1946 			std::forward<F>(f)();
1947 			return nullopt;
1948 		}
1949 
1950 		/// \exclude
1951 		template <class F, detail::disable_if_ret_void<F>* = nullptr>
or_else(F && f) const1952 		optional<T> or_else(F&& f) const&& {
1953 			return has_value() ? std::move(*this) : std::forward<F>(f)();
1954 		}
1955 #endif
1956 
1957 		/// \brief Maps the stored value with `f` if there is one, otherwise returns
1958 		/// `u`.
1959 		///
1960 		/// \details If there is a value stored, then `f` is called with `**this`
1961 		/// and the value is returned. Otherwise `u` is returned.
1962 		///
1963 		/// \group map_or
1964 		template <class F, class U>
map_or(F && f,U && u)1965 		U map_or(F&& f, U&& u) & {
1966 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u);
1967 		}
1968 
1969 		/// \group map_or
1970 		template <class F, class U>
map_or(F && f,U && u)1971 		U map_or(F&& f, U&& u) && {
1972 			return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u);
1973 		}
1974 
1975 		/// \group map_or
1976 		template <class F, class U>
map_or(F && f,U && u) const1977 		U map_or(F&& f, U&& u) const& {
1978 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u);
1979 		}
1980 
1981 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
1982 		/// \group map_or
1983 		template <class F, class U>
map_or(F && f,U && u) const1984 		U map_or(F&& f, U&& u) const&& {
1985 			return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u);
1986 		}
1987 #endif
1988 
1989 		/// \brief Maps the stored value with `f` if there is one, otherwise calls
1990 		/// `u` and returns the result.
1991 		///
1992 		/// \details If there is a value stored, then `f` is
1993 		/// called with `**this` and the value is returned. Otherwise
1994 		/// `std::forward<U>(u)()` is returned.
1995 		///
1996 		/// \group map_or_else
1997 		/// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u) &;
1998 		template <class F, class U>
map_or_else(F && f,U && u)1999 		detail::invoke_result_t<U> map_or_else(F&& f, U&& u) & {
2000 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)();
2001 		}
2002 
2003 		/// \group map_or_else
2004 		/// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u)
2005 		/// &&;
2006 		template <class F, class U>
map_or_else(F && f,U && u)2007 		detail::invoke_result_t<U> map_or_else(F&& f, U&& u) && {
2008 			return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)();
2009 		}
2010 
2011 		/// \group map_or_else
2012 		/// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u)
2013 		/// const &;
2014 		template <class F, class U>
map_or_else(F && f,U && u) const2015 		detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const& {
2016 			return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)();
2017 		}
2018 
2019 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
2020 		/// \group map_or_else
2021 		/// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u)
2022 		/// const &&;
2023 		template <class F, class U>
map_or_else(F && f,U && u) const2024 		detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const&& {
2025 			return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)();
2026 		}
2027 #endif
2028 
2029 		/// \returns `u` if `*this` has a value, otherwise an empty optional.
2030 		template <class U>
conjunction(U && u) const2031 		constexpr optional<typename std::decay<U>::type> conjunction(U&& u) const {
2032 			using result = optional<detail::decay_t<U>>;
2033 			return has_value() ? result { u } : result { nullopt };
2034 		}
2035 
2036 		/// \returns `rhs` if `*this` is empty, otherwise the current value.
2037 		/// \group disjunction
disjunction(const optional & rhs)2038 		SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) & {
2039 			return has_value() ? *this : rhs;
2040 		}
2041 
2042 		/// \group disjunction
disjunction(const optional & rhs) const2043 		constexpr optional disjunction(const optional& rhs) const& {
2044 			return has_value() ? *this : rhs;
2045 		}
2046 
2047 		/// \group disjunction
disjunction(const optional & rhs)2048 		SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) && {
2049 			return has_value() ? std::move(*this) : rhs;
2050 		}
2051 
2052 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
2053 		/// \group disjunction
disjunction(const optional & rhs) const2054 		constexpr optional disjunction(const optional& rhs) const&& {
2055 			return has_value() ? std::move(*this) : rhs;
2056 		}
2057 #endif
2058 
2059 		/// \group disjunction
disjunction(optional && rhs)2060 		SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) & {
2061 			return has_value() ? *this : std::move(rhs);
2062 		}
2063 
2064 		/// \group disjunction
disjunction(optional && rhs) const2065 		constexpr optional disjunction(optional&& rhs) const& {
2066 			return has_value() ? *this : std::move(rhs);
2067 		}
2068 
2069 		/// \group disjunction
disjunction(optional && rhs)2070 		SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) && {
2071 			return has_value() ? std::move(*this) : std::move(rhs);
2072 		}
2073 
2074 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
2075 		/// \group disjunction
disjunction(optional && rhs) const2076 		constexpr optional disjunction(optional&& rhs) const&& {
2077 			return has_value() ? std::move(*this) : std::move(rhs);
2078 		}
2079 #endif
2080 
2081 		/// Takes the value out of the optional, leaving it empty
2082 		/// \group take
take()2083 		optional take() & {
2084 			optional ret = *this;
2085 			reset();
2086 			return ret;
2087 		}
2088 
2089 		/// \group take
take() const2090 		optional take() const& {
2091 			optional ret = *this;
2092 			reset();
2093 			return ret;
2094 		}
2095 
2096 		/// \group take
take()2097 		optional take() && {
2098 			optional ret = std::move(*this);
2099 			reset();
2100 			return ret;
2101 		}
2102 
2103 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR
2104 		/// \group take
take() const2105 		optional take() const&& {
2106 			optional ret = std::move(*this);
2107 			reset();
2108 			return ret;
2109 		}
2110 #endif
2111 
2112 		using value_type = T&;
2113 
2114 		/// Constructs an optional that does not contain a value.
2115 		/// \group ctor_empty
optional()2116 		constexpr optional() noexcept : m_value(nullptr) {
2117 		}
2118 
2119 		/// \group ctor_empty
optional(nullopt_t)2120 		constexpr optional(nullopt_t) noexcept : m_value(nullptr) {
2121 		}
2122 
2123 		/// Copy constructor
2124 		///
2125 		/// If `rhs` contains a value, the stored value is direct-initialized with
2126 		/// it. Otherwise, the constructed optional is empty.
2127 		SOL_TL_OPTIONAL_11_CONSTEXPR optional(const optional& rhs) noexcept = default;
2128 
2129 		/// Move constructor
2130 		///
2131 		/// If `rhs` contains a value, the stored value is direct-initialized with
2132 		/// it. Otherwise, the constructed optional is empty.
2133 		SOL_TL_OPTIONAL_11_CONSTEXPR optional(optional&& rhs) = default;
2134 
2135 		/// Constructs the stored value with `u`.
2136 		/// \synopsis template <class U=T> constexpr optional(U &&u);
2137 		template <class U = T, detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>* = nullptr>
optional(U && u)2138 		constexpr optional(U&& u) : m_value(std::addressof(u)) {
2139 			static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue");
2140 		}
2141 
2142 		/// \exclude
2143 		template <class U>
optional(const optional<U> & rhs)2144 		constexpr explicit optional(const optional<U>& rhs) : optional(*rhs) {
2145 		}
2146 
2147 		/// No-op
2148 		~optional() = default;
2149 
2150 		/// Assignment to empty.
2151 		///
2152 		/// Destroys the current value if there is one.
operator =(nullopt_t)2153 		optional& operator=(nullopt_t) noexcept {
2154 			m_value = nullptr;
2155 			return *this;
2156 		}
2157 
2158 		/// Copy assignment.
2159 		///
2160 		/// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
2161 		/// resets the stored value in `*this`.
2162 		optional& operator=(const optional& rhs) = default;
2163 
2164 		/// Rebinds this optional to `u`.
2165 		///
2166 		/// \requires `U` must be an lvalue reference.
2167 		/// \synopsis optional &operator=(U &&u);
2168 		template <class U = T, detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>* = nullptr>
operator =(U && u)2169 		optional& operator=(U&& u) {
2170 			static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue");
2171 			m_value = std::addressof(u);
2172 			return *this;
2173 		}
2174 
2175 		/// Converting copy assignment operator.
2176 		///
2177 		/// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
2178 		/// resets the stored value in `*this`.
2179 		template <class U>
operator =(const optional<U> & rhs)2180 		optional& operator=(const optional<U>& rhs) {
2181 			m_value = std::addressof(rhs.value());
2182 			return *this;
2183 		}
2184 
2185 		/// Constructs the value in-place, destroying the current one if there is
2186 		/// one.
2187 		///
2188 		/// \group emplace
2189 		template <class... Args>
emplace(Args &&...args)2190 		T& emplace(Args&&... args) noexcept {
2191 			static_assert(std::is_constructible<T, Args&&...>::value, "T must be constructible with Args");
2192 
2193 			*this = nullopt;
2194 			this->construct(std::forward<Args>(args)...);
2195 		}
2196 
2197 		/// Swaps this optional with the other.
2198 		///
2199 		/// If neither optionals have a value, nothing happens.
2200 		/// If both have a value, the values are swapped.
2201 		/// If one has a value, it is moved to the other and the movee is left
2202 		/// valueless.
swap(optional & rhs)2203 		void swap(optional& rhs) noexcept {
2204 			std::swap(m_value, rhs.m_value);
2205 		}
2206 
2207 		/// \returns a pointer to the stored value
2208 		/// \requires a value is stored
2209 		/// \group pointer
2210 		/// \synopsis constexpr const T *operator->() const;
operator ->() const2211 		constexpr const T* operator->() const {
2212 			return m_value;
2213 		}
2214 
2215 		/// \group pointer
2216 		/// \synopsis constexpr T *operator->();
operator ->()2217 		SOL_TL_OPTIONAL_11_CONSTEXPR T* operator->() {
2218 			return m_value;
2219 		}
2220 
2221 		/// \returns the stored value
2222 		/// \requires a value is stored
2223 		/// \group deref
2224 		/// \synopsis constexpr T &operator*();
operator *()2225 		SOL_TL_OPTIONAL_11_CONSTEXPR T& operator*() {
2226 			return *m_value;
2227 		}
2228 
2229 		/// \group deref
2230 		/// \synopsis constexpr const T &operator*() const;
operator *() const2231 		constexpr const T& operator*() const {
2232 			return *m_value;
2233 		}
2234 
2235 		/// \returns whether or not the optional has a value
2236 		/// \group has_value
has_value() const2237 		constexpr bool has_value() const noexcept {
2238 			return m_value != nullptr;
2239 		}
2240 
2241 		/// \group has_value
operator bool() const2242 		constexpr explicit operator bool() const noexcept {
2243 			return m_value != nullptr;
2244 		}
2245 
2246 		/// \returns the contained value if there is one, otherwise throws
2247 		/// [bad_optional_access]
2248 		/// \group value
2249 		/// synopsis constexpr T &value();
value()2250 		SOL_TL_OPTIONAL_11_CONSTEXPR T& value() {
2251 			if (has_value())
2252 				return *m_value;
2253 #if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
2254 			std::abort();
2255 #else
2256 			throw bad_optional_access();
2257 #endif // No exceptions allowed
2258 		}
2259 		/// \group value
2260 		/// \synopsis constexpr const T &value() const;
value() const2261 		SOL_TL_OPTIONAL_11_CONSTEXPR const T& value() const {
2262 			if (has_value())
2263 				return *m_value;
2264 #if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
2265 			std::abort();
2266 #else
2267 			throw bad_optional_access();
2268 #endif // No exceptions allowed
2269 		}
2270 
2271 		/// \returns the stored value if there is one, otherwise returns `u`
2272 		/// \group value_or
2273 		template <class U>
value_or(U && u) const2274 		constexpr T& value_or(U&& u) const {
2275 			static_assert(std::is_convertible<U&&, T&>::value, "T must be convertible from U");
2276 			return has_value() ? const_cast<T&>(**this) : static_cast<T&>(std::forward<U>(u));
2277 		}
2278 
2279 		/// Destroys the stored value if one exists, making the optional empty
reset()2280 		void reset() noexcept {
2281 			m_value = nullptr;
2282 		}
2283 
2284 	private:
2285 		T* m_value;
2286 	};
2287 
2288 } // namespace sol
2289 
2290 namespace std {
2291 	// TODO SFINAE
2292 	template <class T>
2293 	struct hash<::sol::optional<T>> {
operator ()std::hash2294 		::std::size_t operator()(const ::sol::optional<T>& o) const {
2295 			if (!o.has_value())
2296 				return 0;
2297 
2298 			return ::std::hash<::sol::detail::remove_const_t<T>>()(*o);
2299 		}
2300 	};
2301 } // namespace std
2302 
2303 #endif // SOL_TL_OPTIONAL_HPP
2304