scc 2025.09
SystemC components library
optional.hpp
1
3// optional - An implementation of std::optional with extensions
4// Written in 2017 by Sy Brand (tartanllama@gmail.com, @TartanLlama)
5//
6// Documentation available at https://tl.tartanllama.xyz/
7//
8// To the extent possible under law, the author(s) have dedicated all
9// copyright and related and neighboring rights to this software to the
10// public domain worldwide. This software is distributed without any warranty.
11//
12// You should have received a copy of the CC0 Public Domain Dedication
13// along with this software. If not, see
14// <http://creativecommons.org/publicdomain/zero/1.0/>.
16
17#pragma once
18
19#if __cplusplus > 201402L
20#include <optional>
21namespace nonstd {
22using std::optional;
23}
24#else
25#ifndef TL_OPTIONAL_HPP
26#define TL_OPTIONAL_HPP
27
28#define TL_OPTIONAL_VERSION_MAJOR 1
29#define TL_OPTIONAL_VERSION_MINOR 1
30#define TL_OPTIONAL_VERSION_PATCH 0
31
32#include <exception>
33#include <functional>
34#include <type_traits>
35#include <utility>
36
37#if(defined(_MSC_VER) && _MSC_VER == 1900)
38#define TL_OPTIONAL_MSVC2015
39#endif
40
41#if(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__))
42#define TL_OPTIONAL_GCC49
43#endif
44
45#if(defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && !defined(__clang__))
46#define TL_OPTIONAL_GCC54
47#endif
48
49#if(defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && !defined(__clang__))
50#define TL_OPTIONAL_GCC55
51#endif
52
53#if(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__))
54// GCC < 5 doesn't support overloading on const&& for member functions
55#define TL_OPTIONAL_NO_CONSTRR
56
57// GCC < 5 doesn't support some standard C++11 type traits
58#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::has_trivial_copy_constructor<T>::value
59#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign<T>::value
60
61// This one will be different for GCC 5.7 if it's ever supported
62#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
63
64// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks std::vector
65// for non-copyable types
66#elif(defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))
67#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
68#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
69namespace nonstd {
70namespace detail {
71template <class T> struct is_trivially_copy_constructible : std::is_trivially_copy_constructible<T> {};
72#ifdef _GLIBCXX_VECTOR
73template <class T, class A> struct is_trivially_copy_constructible<std::vector<T, A>> : std::is_trivially_copy_constructible<T> {};
74#endif
75} // namespace detail
76} // namespace nonstd
77#endif
78
79#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) nonstd::detail::is_trivially_copy_constructible<T>::value
80#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable<T>::value
81#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
82#else
83#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::is_trivially_copy_constructible<T>::value
84#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable<T>::value
85#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
86#endif
87
88#if __cplusplus > 201103L
89#define TL_OPTIONAL_CXX14
90#endif
91
92// constexpr implies const in C++11, not C++14
93#if(__cplusplus == 201103L || defined(TL_OPTIONAL_MSVC2015) || defined(TL_OPTIONAL_GCC49))
94#define TL_OPTIONAL_11_CONSTEXPR
95#else
96#define TL_OPTIONAL_11_CONSTEXPR constexpr
97#endif
98
99namespace nonstd {
100#ifndef TL_MONOSTATE_INPLACE_MUTEX
101#define TL_MONOSTATE_INPLACE_MUTEX
103class monostate {};
104
106struct in_place_t {
107 explicit in_place_t() = default;
108};
109
110static constexpr in_place_t in_place{};
111#endif
112
113template <class T> class optional;
114
115namespace detail {
116#ifndef TL_TRAITS_MUTEX
117#define TL_TRAITS_MUTEX
118// C++14-style aliases for brevity
119template <class T> using remove_const_t = typename std::remove_const<T>::type;
120template <class T> using remove_reference_t = typename std::remove_reference<T>::type;
121template <class T> using decay_t = typename std::decay<T>::type;
122template <bool E, class T = void> using enable_if_t = typename std::enable_if<E, T>::type;
123template <bool B, class T, class F> using conditional_t = typename std::conditional<B, T, F>::type;
124
125// std::conjunction from C++17
126template <class...> struct conjunction : std::true_type {};
127template <class B> struct conjunction<B> : B {};
128template <class B, class... Bs> struct conjunction<B, Bs...> : std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};
129
130#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L
131#define TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
132#endif
133
134// In C++11 mode, there's an issue in libc++'s std::mem_fn
135// which results in a hard-error when using it in a noexcept expression
136// in some cases. This is a check to workaround the common failing case.
137#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
138template <class T> struct is_pointer_to_non_const_member_func : std::false_type {};
139template <class T, class Ret, class... Args> struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)> : std::true_type {};
140template <class T, class Ret, class... Args> struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)&> : std::true_type {};
141template <class T, class Ret, class... Args> struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &&> : std::true_type {};
142template <class T, class Ret, class... Args> struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile> : std::true_type {};
143template <class T, class Ret, class... Args> struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile&> : std::true_type {};
144template <class T, class Ret, class... Args> struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile&&> : std::true_type {};
145
146template <class T> struct is_const_or_const_ref : std::false_type {};
147template <class T> struct is_const_or_const_ref<T const&> : std::true_type {};
148template <class T> struct is_const_or_const_ref<T const> : std::true_type {};
149#endif
150
151// std::invoke from C++17
152// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround
153template <typename Fn, typename... Args,
154#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
155 typename = enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value && is_const_or_const_ref<Args...>::value)>,
156#endif
157 typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>, int = 0>
158constexpr auto invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
159 -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {
160 return std::mem_fn(f)(std::forward<Args>(args)...);
161}
162
163template <typename Fn, typename... Args, typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>>
164constexpr auto invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
165 -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {
166 return std::forward<Fn>(f)(std::forward<Args>(args)...);
167}
168
169// std::invoke_result from C++17
170template <class F, class, class... Us> struct invoke_result_impl;
171
172template <class F, class... Us>
173struct invoke_result_impl<F, decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()), Us...> {
174 using type = decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...));
175};
176
177template <class F, class... Us> using invoke_result = invoke_result_impl<F, void, Us...>;
178
179template <class F, class... Us> using invoke_result_t = typename invoke_result<F, Us...>::type;
180
181#if defined(_MSC_VER) && _MSC_VER <= 1900
182// TODO make a version which works with MSVC 2015
183template <class T, class U = T> struct is_swappable : std::true_type {};
184
185template <class T, class U = T> struct is_nothrow_swappable : std::true_type {};
186#else
187// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
188namespace swap_adl_tests {
189// if swap ADL finds this then it would call std::swap otherwise (same
190// signature)
191struct tag {};
192
193template <class T> tag swap(T&, T&);
194template <class T, std::size_t N> tag swap(T (&a)[N], T (&b)[N]);
195
196// helper functions to test if an unqualified swap is possible, and if it
197// becomes std::swap
198template <class, class> std::false_type can_swap(...) noexcept(false);
199template <class T, class U, class = decltype(swap(std::declval<T&>(), std::declval<U&>()))>
200std::true_type can_swap(int) noexcept(noexcept(swap(std::declval<T&>(), std::declval<U&>())));
201
202template <class, class> std::false_type uses_std(...);
203template <class T, class U> std::is_same<decltype(swap(std::declval<T&>(), std::declval<U&>())), tag> uses_std(int);
204
205template <class T>
207: std::integral_constant<bool, std::is_nothrow_move_constructible<T>::value && std::is_nothrow_move_assignable<T>::value> {};
208
209template <class T, std::size_t N> struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};
210
211template <class T, class U> struct is_adl_swap_noexcept : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};
212} // namespace swap_adl_tests
213
214template <class T, class U = T>
215struct is_swappable : std::integral_constant<bool, decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
216 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
217 (std::is_move_assignable<T>::value && std::is_move_constructible<T>::value))> {};
218
219template <class T, std::size_t N>
220struct is_swappable<T[N], T[N]>
221: std::integral_constant<bool, decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
222 (!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value || is_swappable<T, T>::value)> {};
223
224template <class T, class U = T>
226: std::integral_constant<bool, is_swappable<T, U>::value && ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
227 detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||
228 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
229 detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> {};
230#endif
231#endif
232
233// std::void_t from C++17
234template <class...> struct voider { using type = void; };
235template <class... Ts> using void_t = typename voider<Ts...>::type;
236
237// Trait for checking if a type is a nonstd::optional
238template <class T> struct is_optional_impl : std::false_type {};
239template <class T> struct is_optional_impl<optional<T>> : std::true_type {};
240template <class T> using is_optional = is_optional_impl<decay_t<T>>;
241
242// Change void to nonstd::monostate
243template <class U> using fixup_void = conditional_t<std::is_void<U>::value, monostate, U>;
244
245template <class F, class U, class = invoke_result_t<F, U>> using get_map_return = optional<fixup_void<invoke_result_t<F, U>>>;
246
247// Check if invoking F for some Us returns void
248template <class F, class = void, class... U> struct returns_void_impl;
249template <class F, class... U>
250struct returns_void_impl<F, void_t<invoke_result_t<F, U...>>, U...> : std::is_void<invoke_result_t<F, U...>> {};
251template <class F, class... U> using returns_void = returns_void_impl<F, void, U...>;
252
253template <class T, class... U> using enable_if_ret_void = enable_if_t<returns_void<T&&, U...>::value>;
254
255template <class T, class... U> using disable_if_ret_void = enable_if_t<!returns_void<T&&, U...>::value>;
256
257template <class T, class U>
258using enable_forward_value =
259 detail::enable_if_t<std::is_constructible<T, U&&>::value && !std::is_same<detail::decay_t<U>, in_place_t>::value &&
260 !std::is_same<optional<T>, detail::decay_t<U>>::value>;
261
262template <class T, class U, class Other>
263using enable_from_other =
264 detail::enable_if_t<std::is_constructible<T, Other>::value && !std::is_constructible<T, optional<U>&>::value &&
265 !std::is_constructible<T, optional<U>&&>::value && !std::is_constructible<T, const optional<U>&>::value &&
266 !std::is_constructible<T, const optional<U>&&>::value && !std::is_convertible<optional<U>&, T>::value &&
267 !std::is_convertible<optional<U>&&, T>::value && !std::is_convertible<const optional<U>&, T>::value &&
268 !std::is_convertible<const optional<U>&&, T>::value>;
269
270template <class T, class U>
271using enable_assign_forward = detail::enable_if_t<!std::is_same<optional<T>, detail::decay_t<U>>::value &&
272 !detail::conjunction<std::is_scalar<T>, std::is_same<T, detail::decay_t<U>>>::value &&
273 std::is_constructible<T, U>::value && std::is_assignable<T&, U>::value>;
274
275template <class T, class U, class Other>
276using enable_assign_from_other =
277 detail::enable_if_t<std::is_constructible<T, Other>::value && std::is_assignable<T&, Other>::value &&
278 !std::is_constructible<T, optional<U>&>::value && !std::is_constructible<T, optional<U>&&>::value &&
279 !std::is_constructible<T, const optional<U>&>::value && !std::is_constructible<T, const optional<U>&&>::value &&
280 !std::is_convertible<optional<U>&, T>::value && !std::is_convertible<optional<U>&&, T>::value &&
281 !std::is_convertible<const optional<U>&, T>::value && !std::is_convertible<const optional<U>&&, T>::value &&
282 !std::is_assignable<T&, optional<U>&>::value && !std::is_assignable<T&, optional<U>&&>::value &&
283 !std::is_assignable<T&, const optional<U>&>::value && !std::is_assignable<T&, const optional<U>&&>::value>;
284
285// The storage base manages the actual storage, and correctly propagates
286// trivial destruction from T. This case is for when T is not trivially
287// destructible.
288template <class T, bool = ::std::is_trivially_destructible<T>::value> struct optional_storage_base {
289 TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
290 : m_dummy()
291 , m_has_value(false) {}
292
293 template <class... U>
294 TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U&&... u)
295 : m_value(std::forward<U>(u)...)
296 , m_has_value(true) {}
297
298 ~optional_storage_base() {
299 if(m_has_value) {
300 m_value.~T();
301 m_has_value = false;
302 }
303 }
304
305 struct dummy {};
306 union {
307 dummy m_dummy;
308 T m_value;
309 };
310
311 bool m_has_value;
312};
313
314// This case is for when T is trivially destructible.
315template <class T> struct optional_storage_base<T, true> {
316 TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
317 : m_dummy()
318 , m_has_value(false) {}
319
320 template <class... U>
321 TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U&&... u)
322 : m_value(std::forward<U>(u)...)
323 , m_has_value(true) {}
324
325 // No destructor, so this class is trivially destructible
326
327 struct dummy {};
328 union {
329 dummy m_dummy;
330 T m_value;
331 };
332
333 bool m_has_value = false;
334};
335
336// This base class provides some handy member functions which can be used in
337// further derived classes
338template <class T> struct optional_operations_base : optional_storage_base<T> {
339 using optional_storage_base<T>::optional_storage_base;
340
341 void hard_reset() noexcept {
342 get().~T();
343 this->m_has_value = false;
344 }
345
346 template <class... Args> void construct(Args&&... args) {
347 new(std::addressof(this->m_value)) T(std::forward<Args>(args)...);
348 this->m_has_value = true;
349 }
350
351 template <class Opt> void assign(Opt&& rhs) {
352 if(this->has_value()) {
353 if(rhs.has_value()) {
354 this->m_value = std::forward<Opt>(rhs).get();
355 } else {
356 this->m_value.~T();
357 this->m_has_value = false;
358 }
359 }
360
361 else if(rhs.has_value()) {
362 construct(std::forward<Opt>(rhs).get());
363 }
364 }
365
366 bool has_value() const { return this->m_has_value; }
367
368 TL_OPTIONAL_11_CONSTEXPR T& get() & { return this->m_value; }
369 TL_OPTIONAL_11_CONSTEXPR const T& get() const& { return this->m_value; }
370 TL_OPTIONAL_11_CONSTEXPR T&& get() && { return std::move(this->m_value); }
371#ifndef TL_OPTIONAL_NO_CONSTRR
372 constexpr const T&& get() const&& { return std::move(this->m_value); }
373#endif
374};
375
376// This class manages conditionally having a trivial copy constructor
377// This specialization is for when T is trivially copy constructible
378template <class T, bool = TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)> struct optional_copy_base : optional_operations_base<T> {
380};
381
382// This specialization is for when T is not trivially copy constructible
383template <class T> struct optional_copy_base<T, false> : optional_operations_base<T> {
385
386 optional_copy_base() = default;
387 optional_copy_base(const optional_copy_base& rhs)
389 if(rhs.has_value()) {
390 this->construct(rhs.get());
391 } else {
392 this->m_has_value = false;
393 }
394 }
395
396 optional_copy_base(optional_copy_base&& rhs) = default;
397 optional_copy_base& operator=(const optional_copy_base& rhs) = default;
398 optional_copy_base& operator=(optional_copy_base&& rhs) = default;
399};
400
401// This class manages conditionally having a trivial move constructor
402// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
403// doesn't implement an analogue to std::is_trivially_move_constructible. We
404// have to make do with a non-trivial move constructor even if T is trivially
405// move constructible
406#ifndef TL_OPTIONAL_GCC49
407template <class T, bool = std::is_trivially_move_constructible<T>::value> struct optional_move_base : optional_copy_base<T> {
409};
410#else
411template <class T, bool = false> struct optional_move_base;
412#endif
413template <class T> struct optional_move_base<T, false> : optional_copy_base<T> {
415
416 optional_move_base() = default;
417 optional_move_base(const optional_move_base& rhs) = default;
418
419 optional_move_base(optional_move_base&& rhs) noexcept(std::is_nothrow_move_constructible<T>::value) {
420 if(rhs.has_value()) {
421 this->construct(std::move(rhs.get()));
422 } else {
423 this->m_has_value = false;
424 }
425 }
426 optional_move_base& operator=(const optional_move_base& rhs) = default;
427 optional_move_base& operator=(optional_move_base&& rhs) = default;
428};
429
430// This class manages conditionally having a trivial copy assignment operator
431template <class T, bool = TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) && TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) &&
432 TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T)>
436
437template <class T> struct optional_copy_assign_base<T, false> : optional_move_base<T> {
439
440 optional_copy_assign_base() = default;
441 optional_copy_assign_base(const optional_copy_assign_base& rhs) = default;
442
443 optional_copy_assign_base(optional_copy_assign_base&& rhs) = default;
444 optional_copy_assign_base& operator=(const optional_copy_assign_base& rhs) {
445 this->assign(rhs);
446 return *this;
447 }
448 optional_copy_assign_base& operator=(optional_copy_assign_base&& rhs) = default;
449};
450
451// This class manages conditionally having a trivial move assignment operator
452// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
453// doesn't implement an analogue to std::is_trivially_move_assignable. We have
454// to make do with a non-trivial move assignment operator even if T is trivially
455// move assignable
456#ifndef TL_OPTIONAL_GCC49
457template <class T, bool = std::is_trivially_destructible<T>::value&& std::is_trivially_move_constructible<T>::value&&
458 std::is_trivially_move_assignable<T>::value>
462#else
463template <class T, bool = false> struct optional_move_assign_base;
464#endif
465
466template <class T> struct optional_move_assign_base<T, false> : optional_copy_assign_base<T> {
468
469 optional_move_assign_base() = default;
470 optional_move_assign_base(const optional_move_assign_base& rhs) = default;
471
472 optional_move_assign_base(optional_move_assign_base&& rhs) = default;
473
474 optional_move_assign_base& operator=(const optional_move_assign_base& rhs) = default;
475
476 optional_move_assign_base& operator=(optional_move_assign_base&& rhs) noexcept(
477 std::is_nothrow_move_constructible<T>::value&& std::is_nothrow_move_assignable<T>::value) {
478 this->assign(std::move(rhs));
479 return *this;
480 }
481};
482
483// optional_delete_ctor_base will conditionally delete copy and move
484// constructors depending on whether T is copy/move constructible
485template <class T, bool EnableCopy = std::is_copy_constructible<T>::value, bool EnableMove = std::is_move_constructible<T>::value>
486struct optional_delete_ctor_base {
487 optional_delete_ctor_base() = default;
488 optional_delete_ctor_base(const optional_delete_ctor_base&) = default;
489 optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = default;
490 optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default;
491 optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default;
492};
493
494template <class T> struct optional_delete_ctor_base<T, true, false> {
495 optional_delete_ctor_base() = default;
496 optional_delete_ctor_base(const optional_delete_ctor_base&) = default;
497 optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = delete;
498 optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default;
499 optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default;
500};
501
502template <class T> struct optional_delete_ctor_base<T, false, true> {
503 optional_delete_ctor_base() = default;
504 optional_delete_ctor_base(const optional_delete_ctor_base&) = delete;
505 optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = default;
506 optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default;
507 optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default;
508};
509
510template <class T> struct optional_delete_ctor_base<T, false, false> {
511 optional_delete_ctor_base() = default;
512 optional_delete_ctor_base(const optional_delete_ctor_base&) = delete;
513 optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = delete;
514 optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default;
515 optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default;
516};
517
518// optional_delete_assign_base will conditionally delete copy and move
519// constructors depending on whether T is copy/move constructible + assignable
520template <class T, bool EnableCopy = (std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value),
521 bool EnableMove = (std::is_move_constructible<T>::value && std::is_move_assignable<T>::value)>
522struct optional_delete_assign_base {
523 optional_delete_assign_base() = default;
524 optional_delete_assign_base(const optional_delete_assign_base&) = default;
525 optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default;
526 optional_delete_assign_base& operator=(const optional_delete_assign_base&) = default;
527 optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = default;
528};
529
530template <class T> struct optional_delete_assign_base<T, true, false> {
531 optional_delete_assign_base() = default;
532 optional_delete_assign_base(const optional_delete_assign_base&) = default;
533 optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default;
534 optional_delete_assign_base& operator=(const optional_delete_assign_base&) = default;
535 optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = delete;
536};
537
538template <class T> struct optional_delete_assign_base<T, false, true> {
539 optional_delete_assign_base() = default;
540 optional_delete_assign_base(const optional_delete_assign_base&) = default;
541 optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default;
542 optional_delete_assign_base& operator=(const optional_delete_assign_base&) = delete;
543 optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = default;
544};
545
546template <class T> struct optional_delete_assign_base<T, false, false> {
547 optional_delete_assign_base() = default;
548 optional_delete_assign_base(const optional_delete_assign_base&) = default;
549 optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default;
550 optional_delete_assign_base& operator=(const optional_delete_assign_base&) = delete;
551 optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = delete;
552};
553
554} // namespace detail
555
557struct nullopt_t {
558 struct do_not_use {};
559 constexpr explicit nullopt_t(do_not_use, do_not_use) noexcept {}
560};
561
562static constexpr nullopt_t nullopt{nullopt_t::do_not_use{}, nullopt_t::do_not_use{}};
563
564class bad_optional_access : public std::exception {
565public:
566 bad_optional_access() = default;
567 const char* what() const noexcept { return "Optional has no value"; }
568};
569
576template <class T>
581
582 static_assert(!std::is_same<T, in_place_t>::value, "instantiation of optional with in_place_t is ill-formed");
583 static_assert(!std::is_same<detail::decay_t<T>, nullopt_t>::value, "instantiation of optional with nullopt_t is ill-formed");
584
585public:
586// The different versions for C++14 and 11 are needed because deduced return
587// types are not SFINAE-safe. This provides better support for things like
588// generic lambdas. C.f.
589// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
590#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
593 template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) & {
594 using result = detail::invoke_result_t<F, T&>;
595 static_assert(detail::is_optional<result>::value, "F must return an optional");
596
597 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
598 }
599
600 template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) && {
601 using result = detail::invoke_result_t<F, T&&>;
602 static_assert(detail::is_optional<result>::value, "F must return an optional");
603
604 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt);
605 }
606
607 template <class F> constexpr auto and_then(F&& f) const& {
608 using result = detail::invoke_result_t<F, const T&>;
609 static_assert(detail::is_optional<result>::value, "F must return an optional");
610
611 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
612 }
613
614#ifndef TL_OPTIONAL_NO_CONSTRR
615 template <class F> constexpr auto and_then(F&& f) const&& {
616 using result = detail::invoke_result_t<F, const T&&>;
617 static_assert(detail::is_optional<result>::value, "F must return an optional");
618
619 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt);
620 }
621#endif
622#else
625 template <class F> TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&> and_then(F&& f) & {
626 using result = detail::invoke_result_t<F, T&>;
627 static_assert(detail::is_optional<result>::value, "F must return an optional");
628
629 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
630 }
631
632 template <class F> TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&&> and_then(F&& f) && {
633 using result = detail::invoke_result_t<F, T&&>;
634 static_assert(detail::is_optional<result>::value, "F must return an optional");
635
636 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt);
637 }
638
639 template <class F> constexpr detail::invoke_result_t<F, const T&> and_then(F&& f) const& {
640 using result = detail::invoke_result_t<F, const T&>;
641 static_assert(detail::is_optional<result>::value, "F must return an optional");
642
643 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
644 }
645
646#ifndef TL_OPTIONAL_NO_CONSTRR
647 template <class F> constexpr detail::invoke_result_t<F, const T&&> and_then(F&& f) const&& {
648 using result = detail::invoke_result_t<F, const T&&>;
649 static_assert(detail::is_optional<result>::value, "F must return an optional");
650
651 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt);
652 }
653#endif
654#endif
655
656#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
658 template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) & { return optional_map_impl(*this, std::forward<F>(f)); }
659
660 template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) && { return optional_map_impl(std::move(*this), std::forward<F>(f)); }
661
662 template <class F> constexpr auto map(F&& f) const& { return optional_map_impl(*this, std::forward<F>(f)); }
663
664 template <class F> constexpr auto map(F&& f) const&& { return optional_map_impl(std::move(*this), std::forward<F>(f)); }
665#else
667 template <class F> TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&>(), std::declval<F&&>())) map(F&& f) & {
668 return optional_map_impl(*this, std::forward<F>(f));
669 }
670
671 template <class F> TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&&>(), std::declval<F&&>())) map(F&& f) && {
672 return optional_map_impl(std::move(*this), std::forward<F>(f));
673 }
674
675 template <class F> constexpr decltype(optional_map_impl(std::declval<const optional&>(), std::declval<F&&>())) map(F&& f) const& {
676 return optional_map_impl(*this, std::forward<F>(f));
677 }
678
679#ifndef TL_OPTIONAL_NO_CONSTRR
680 template <class F> constexpr decltype(optional_map_impl(std::declval<const optional&&>(), std::declval<F&&>())) map(F&& f) const&& {
681 return optional_map_impl(std::move(*this), std::forward<F>(f));
682 }
683#endif
684#endif
685
686#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
688 template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) & { return optional_map_impl(*this, std::forward<F>(f)); }
689
690 template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) && { return optional_map_impl(std::move(*this), std::forward<F>(f)); }
691
692 template <class F> constexpr auto transform(F&& f) const& { return optional_map_impl(*this, std::forward<F>(f)); }
693
694 template <class F> constexpr auto transform(F&& f) const&& { return optional_map_impl(std::move(*this), std::forward<F>(f)); }
695#else
697 template <class F>
698 TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&>(), std::declval<F&&>())) transform(F&& f) & {
699 return optional_map_impl(*this, std::forward<F>(f));
700 }
701
702 template <class F>
703 TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&&>(), std::declval<F&&>())) transform(F&& f) && {
704 return optional_map_impl(std::move(*this), std::forward<F>(f));
705 }
706
707 template <class F> constexpr decltype(optional_map_impl(std::declval<const optional&>(), std::declval<F&&>())) transform(F&& f) const& {
708 return optional_map_impl(*this, std::forward<F>(f));
709 }
710
711#ifndef TL_OPTIONAL_NO_CONSTRR
712 template <class F>
713 constexpr decltype(optional_map_impl(std::declval<const optional&&>(), std::declval<F&&>())) transform(F&& f) const&& {
714 return optional_map_impl(std::move(*this), std::forward<F>(f));
715 }
716#endif
717#endif
718
720 template <class F, detail::enable_if_ret_void<F>* = nullptr> optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & {
721 if(has_value())
722 return *this;
723
724 std::forward<F>(f)();
725 return nullopt;
726 }
727
728 template <class F, detail::disable_if_ret_void<F>* = nullptr> optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & {
729 return has_value() ? *this : std::forward<F>(f)();
730 }
731
732 template <class F, detail::enable_if_ret_void<F>* = nullptr> optional<T> or_else(F&& f) && {
733 if(has_value())
734 return std::move(*this);
735
736 std::forward<F>(f)();
737 return nullopt;
738 }
739
740 template <class F, detail::disable_if_ret_void<F>* = nullptr> optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) && {
741 return has_value() ? std::move(*this) : std::forward<F>(f)();
742 }
743
744 template <class F, detail::enable_if_ret_void<F>* = nullptr> optional<T> or_else(F&& f) const& {
745 if(has_value())
746 return *this;
747
748 std::forward<F>(f)();
749 return nullopt;
750 }
751
752 template <class F, detail::disable_if_ret_void<F>* = nullptr> optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) const& {
753 return has_value() ? *this : std::forward<F>(f)();
754 }
755
756#ifndef TL_OPTIONAL_NO_CONSTRR
757 template <class F, detail::enable_if_ret_void<F>* = nullptr> optional<T> or_else(F&& f) const&& {
758 if(has_value())
759 return std::move(*this);
760
761 std::forward<F>(f)();
762 return nullopt;
763 }
764
765 template <class F, detail::disable_if_ret_void<F>* = nullptr> optional<T> or_else(F&& f) const&& {
766 return has_value() ? std::move(*this) : std::forward<F>(f)();
767 }
768#endif
769
771 template <class F, class U> U map_or(F&& f, U&& u) & {
772 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u);
773 }
774
775 template <class F, class U> U map_or(F&& f, U&& u) && {
776 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u);
777 }
778
779 template <class F, class U> U map_or(F&& f, U&& u) const& {
780 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u);
781 }
782
783#ifndef TL_OPTIONAL_NO_CONSTRR
784 template <class F, class U> U map_or(F&& f, U&& u) const&& {
785 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u);
786 }
787#endif
788
791 template <class F, class U> detail::invoke_result_t<U> map_or_else(F&& f, U&& u) & {
792 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)();
793 }
794
795 template <class F, class U> detail::invoke_result_t<U> map_or_else(F&& f, U&& u) && {
796 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)();
797 }
798
799 template <class F, class U> detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const& {
800 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)();
801 }
802
803#ifndef TL_OPTIONAL_NO_CONSTRR
804 template <class F, class U> detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const&& {
805 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)();
806 }
807#endif
808
810 template <class U> constexpr optional<typename std::decay<U>::type> conjunction(U&& u) const {
811 using result = optional<detail::decay_t<U>>;
812 return has_value() ? result{u} : result{nullopt};
813 }
814
816 TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) & { return has_value() ? *this : rhs; }
817
818 constexpr optional disjunction(const optional& rhs) const& { return has_value() ? *this : rhs; }
819
820 TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) && { return has_value() ? std::move(*this) : rhs; }
821
822#ifndef TL_OPTIONAL_NO_CONSTRR
823 constexpr optional disjunction(const optional& rhs) const&& { return has_value() ? std::move(*this) : rhs; }
824#endif
825
826 TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) & { return has_value() ? *this : std::move(rhs); }
827
828 constexpr optional disjunction(optional&& rhs) const& { return has_value() ? *this : std::move(rhs); }
829
830 TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) && { return has_value() ? std::move(*this) : std::move(rhs); }
831
832#ifndef TL_OPTIONAL_NO_CONSTRR
833 constexpr optional disjunction(optional&& rhs) const&& { return has_value() ? std::move(*this) : std::move(rhs); }
834#endif
835
838 optional ret = std::move(*this);
839 reset();
840 return ret;
841 }
842
843 using value_type = T;
844
846 constexpr optional() noexcept = default;
847
848 constexpr optional(nullopt_t) noexcept {}
849
854 TL_OPTIONAL_11_CONSTEXPR optional(const optional& rhs) = default;
855
860 TL_OPTIONAL_11_CONSTEXPR optional(optional&& rhs) = default;
861
863 template <class... Args>
864 constexpr explicit optional(detail::enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>, Args&&... args)
865 : base(in_place, std::forward<Args>(args)...) {}
866
867 template <class U, class... Args>
868 TL_OPTIONAL_11_CONSTEXPR explicit optional(
869 detail::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, in_place_t>, std::initializer_list<U> il,
870 Args&&... args) {
871 this->construct(il, std::forward<Args>(args)...);
872 }
873
875 template <class U = T, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr,
876 detail::enable_forward_value<T, U>* = nullptr>
877 constexpr optional(U&& u)
878 : base(in_place, std::forward<U>(u)) {}
879
880 template <class U = T, detail::enable_if_t<!std::is_convertible<U&&, T>::value>* = nullptr,
881 detail::enable_forward_value<T, U>* = nullptr>
882 constexpr explicit optional(U&& u)
883 : base(in_place, std::forward<U>(u)) {}
884
886 template <class U, detail::enable_from_other<T, U, const U&>* = nullptr,
887 detail::enable_if_t<std::is_convertible<const U&, T>::value>* = nullptr>
888 optional(const optional<U>& rhs) {
889 if(rhs.has_value()) {
890 this->construct(*rhs);
891 }
892 }
893
894 template <class U, detail::enable_from_other<T, U, const U&>* = nullptr,
895 detail::enable_if_t<!std::is_convertible<const U&, T>::value>* = nullptr>
896 explicit optional(const optional<U>& rhs) {
897 if(rhs.has_value()) {
898 this->construct(*rhs);
899 }
900 }
901
903 template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr>
905 if(rhs.has_value()) {
906 this->construct(std::move(*rhs));
907 }
908 }
909
910 template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<!std::is_convertible<U&&, T>::value>* = nullptr>
911 explicit optional(optional<U>&& rhs) {
912 if(rhs.has_value()) {
913 this->construct(std::move(*rhs));
914 }
915 }
916
918 ~optional() = default;
919
924 if(has_value()) {
925 this->m_value.~T();
926 this->m_has_value = false;
927 }
928
929 return *this;
930 }
931
936 optional& operator=(const optional& rhs) = default;
937
942 optional& operator=(optional&& rhs) = default;
943
946 template <class U = T, detail::enable_assign_forward<T, U>* = nullptr> optional& operator=(U&& u) {
947 if(has_value()) {
948 this->m_value = std::forward<U>(u);
949 } else {
950 this->construct(std::forward<U>(u));
951 }
952
953 return *this;
954 }
955
960 template <class U, detail::enable_assign_from_other<T, U, const U&>* = nullptr> optional& operator=(const optional<U>& rhs) {
961 if(has_value()) {
962 if(rhs.has_value()) {
963 this->m_value = *rhs;
964 } else {
965 this->hard_reset();
966 }
967 }
968
969 else if(rhs.has_value()) {
970 this->construct(*rhs);
971 }
972
973 return *this;
974 }
975
976 // TODO check exception guarantee
981 template <class U, detail::enable_assign_from_other<T, U, U>* = nullptr> optional& operator=(optional<U>&& rhs) {
982 if(has_value()) {
983 if(rhs.has_value()) {
984 this->m_value = std::move(*rhs);
985 } else {
986 this->hard_reset();
987 }
988 }
989
990 else if(rhs.has_value()) {
991 this->construct(std::move(*rhs));
992 }
993
994 return *this;
995 }
996
999 template <class... Args> T& emplace(Args&&... args) {
1000 static_assert(std::is_constructible<T, Args&&...>::value, "T must be constructible with Args");
1001
1002 *this = nullopt;
1003 this->construct(std::forward<Args>(args)...);
1004 return value();
1005 }
1006
1007 template <class U, class... Args>
1008 detail::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, T&> emplace(std::initializer_list<U> il,
1009 Args&&... args) {
1010 *this = nullopt;
1011 this->construct(il, std::forward<Args>(args)...);
1012 return value();
1013 }
1014
1021 void swap(optional& rhs) noexcept(std::is_nothrow_move_constructible<T>::value&& detail::is_nothrow_swappable<T>::value) {
1022 using std::swap;
1023 if(has_value()) {
1024 if(rhs.has_value()) {
1025 swap(**this, *rhs);
1026 } else {
1027 new(std::addressof(rhs.m_value)) T(std::move(this->m_value));
1028 this->m_value.T::~T();
1029 }
1030 } else if(rhs.has_value()) {
1031 new(std::addressof(this->m_value)) T(std::move(rhs.m_value));
1032 rhs.m_value.T::~T();
1033 }
1034 swap(this->m_has_value, rhs.m_has_value);
1035 }
1036
1038 constexpr const T* operator->() const { return std::addressof(this->m_value); }
1039
1040 TL_OPTIONAL_11_CONSTEXPR T* operator->() { return std::addressof(this->m_value); }
1041
1043 TL_OPTIONAL_11_CONSTEXPR T& operator*() & { return this->m_value; }
1044
1045 constexpr const T& operator*() const& { return this->m_value; }
1046
1047 TL_OPTIONAL_11_CONSTEXPR T&& operator*() && { return std::move(this->m_value); }
1048
1049#ifndef TL_OPTIONAL_NO_CONSTRR
1050 constexpr const T&& operator*() const&& { return std::move(this->m_value); }
1051#endif
1052
1054 constexpr bool has_value() const noexcept { return this->m_has_value; }
1055
1056 constexpr explicit operator bool() const noexcept { return this->m_has_value; }
1057
1059 TL_OPTIONAL_11_CONSTEXPR T& value() & {
1060 if(has_value())
1061 return this->m_value;
1062 throw bad_optional_access();
1063 }
1064 TL_OPTIONAL_11_CONSTEXPR const T& value() const& {
1065 if(has_value())
1066 return this->m_value;
1067 throw bad_optional_access();
1068 }
1069 TL_OPTIONAL_11_CONSTEXPR T&& value() && {
1070 if(has_value())
1071 return std::move(this->m_value);
1072 throw bad_optional_access();
1073 }
1074
1075#ifndef TL_OPTIONAL_NO_CONSTRR
1076 TL_OPTIONAL_11_CONSTEXPR const T&& value() const&& {
1077 if(has_value())
1078 return std::move(this->m_value);
1079 throw bad_optional_access();
1080 }
1081#endif
1082
1084 template <class U> constexpr T value_or(U&& u) const& {
1085 static_assert(std::is_copy_constructible<T>::value && std::is_convertible<U&&, T>::value,
1086 "T must be copy constructible and convertible from U");
1087 return has_value() ? **this : static_cast<T>(std::forward<U>(u));
1088 }
1089
1090 template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U&& u) && {
1091 static_assert(std::is_move_constructible<T>::value && std::is_convertible<U&&, T>::value,
1092 "T must be move constructible and convertible from U");
1093 return has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(u));
1094 }
1095
1097 void reset() noexcept {
1098 if(has_value()) {
1099 this->m_value.~T();
1100 this->m_has_value = false;
1101 }
1102 }
1103}; // namespace tl
1104
1106template <class T, class U> inline constexpr bool operator==(const optional<T>& lhs, const optional<U>& rhs) {
1107 return lhs.has_value() == rhs.has_value() && (!lhs.has_value() || *lhs == *rhs);
1108}
1109template <class T, class U> inline constexpr bool operator!=(const optional<T>& lhs, const optional<U>& rhs) {
1110 return lhs.has_value() != rhs.has_value() || (lhs.has_value() && *lhs != *rhs);
1111}
1112template <class T, class U> inline constexpr bool operator<(const optional<T>& lhs, const optional<U>& rhs) {
1113 return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs);
1114}
1115template <class T, class U> inline constexpr bool operator>(const optional<T>& lhs, const optional<U>& rhs) {
1116 return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs);
1117}
1118template <class T, class U> inline constexpr bool operator<=(const optional<T>& lhs, const optional<U>& rhs) {
1119 return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs);
1120}
1121template <class T, class U> inline constexpr bool operator>=(const optional<T>& lhs, const optional<U>& rhs) {
1122 return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs);
1123}
1124
1126template <class T> inline constexpr bool operator==(const optional<T>& lhs, nullopt_t) noexcept { return !lhs.has_value(); }
1127template <class T> inline constexpr bool operator==(nullopt_t, const optional<T>& rhs) noexcept { return !rhs.has_value(); }
1128template <class T> inline constexpr bool operator!=(const optional<T>& lhs, nullopt_t) noexcept { return lhs.has_value(); }
1129template <class T> inline constexpr bool operator!=(nullopt_t, const optional<T>& rhs) noexcept { return rhs.has_value(); }
1130template <class T> inline constexpr bool operator<(const optional<T>&, nullopt_t) noexcept { return false; }
1131template <class T> inline constexpr bool operator<(nullopt_t, const optional<T>& rhs) noexcept { return rhs.has_value(); }
1132template <class T> inline constexpr bool operator<=(const optional<T>& lhs, nullopt_t) noexcept { return !lhs.has_value(); }
1133template <class T> inline constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept { return true; }
1134template <class T> inline constexpr bool operator>(const optional<T>& lhs, nullopt_t) noexcept { return lhs.has_value(); }
1135template <class T> inline constexpr bool operator>(nullopt_t, const optional<T>&) noexcept { return false; }
1136template <class T> inline constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept { return true; }
1137template <class T> inline constexpr bool operator>=(nullopt_t, const optional<T>& rhs) noexcept { return !rhs.has_value(); }
1138
1140template <class T, class U> inline constexpr bool operator==(const optional<T>& lhs, const U& rhs) {
1141 return lhs.has_value() ? *lhs == rhs : false;
1142}
1143template <class T, class U> inline constexpr bool operator==(const U& lhs, const optional<T>& rhs) {
1144 return rhs.has_value() ? lhs == *rhs : false;
1145}
1146template <class T, class U> inline constexpr bool operator!=(const optional<T>& lhs, const U& rhs) {
1147 return lhs.has_value() ? *lhs != rhs : true;
1148}
1149template <class T, class U> inline constexpr bool operator!=(const U& lhs, const optional<T>& rhs) {
1150 return rhs.has_value() ? lhs != *rhs : true;
1151}
1152template <class T, class U> inline constexpr bool operator<(const optional<T>& lhs, const U& rhs) {
1153 return lhs.has_value() ? *lhs < rhs : true;
1154}
1155template <class T, class U> inline constexpr bool operator<(const U& lhs, const optional<T>& rhs) {
1156 return rhs.has_value() ? lhs < *rhs : false;
1157}
1158template <class T, class U> inline constexpr bool operator<=(const optional<T>& lhs, const U& rhs) {
1159 return lhs.has_value() ? *lhs <= rhs : true;
1160}
1161template <class T, class U> inline constexpr bool operator<=(const U& lhs, const optional<T>& rhs) {
1162 return rhs.has_value() ? lhs <= *rhs : false;
1163}
1164template <class T, class U> inline constexpr bool operator>(const optional<T>& lhs, const U& rhs) {
1165 return lhs.has_value() ? *lhs > rhs : false;
1166}
1167template <class T, class U> inline constexpr bool operator>(const U& lhs, const optional<T>& rhs) {
1168 return rhs.has_value() ? lhs > *rhs : true;
1169}
1170template <class T, class U> inline constexpr bool operator>=(const optional<T>& lhs, const U& rhs) {
1171 return lhs.has_value() ? *lhs >= rhs : false;
1172}
1173template <class T, class U> inline constexpr bool operator>=(const U& lhs, const optional<T>& rhs) {
1174 return rhs.has_value() ? lhs >= *rhs : true;
1175}
1176
1177template <class T, detail::enable_if_t<std::is_move_constructible<T>::value>* = nullptr,
1178 detail::enable_if_t<detail::is_swappable<T>::value>* = nullptr>
1179void swap(optional<T>& lhs, optional<T>& rhs) noexcept(noexcept(lhs.swap(rhs))) {
1180 return lhs.swap(rhs);
1181}
1182
1183namespace detail {
1184struct i_am_secret {};
1185} // namespace detail
1186
1187template <class T = detail::i_am_secret, class U,
1188 class Ret = detail::conditional_t<std::is_same<T, detail::i_am_secret>::value, detail::decay_t<U>, T>>
1189inline constexpr optional<Ret> make_optional(U&& v) {
1190 return optional<Ret>(std::forward<U>(v));
1191}
1192
1193template <class T, class... Args> inline constexpr optional<T> make_optional(Args&&... args) {
1194 return optional<T>(in_place, std::forward<Args>(args)...);
1195}
1196template <class T, class U, class... Args> inline constexpr optional<T> make_optional(std::initializer_list<U> il, Args&&... args) {
1197 return optional<T>(in_place, il, std::forward<Args>(args)...);
1198}
1199
1200#if __cplusplus >= 201703L
1201template <class T> optional(T) -> optional<T>;
1202#endif
1203
1205namespace detail {
1206#ifdef TL_OPTIONAL_CXX14
1207template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())),
1208 detail::enable_if_t<!std::is_void<Ret>::value>* = nullptr>
1209constexpr auto optional_map_impl(Opt&& opt, F&& f) {
1210 return opt.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt)) : optional<Ret>(nullopt);
1211}
1212
1213template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())),
1214 detail::enable_if_t<std::is_void<Ret>::value>* = nullptr>
1215auto optional_map_impl(Opt&& opt, F&& f) {
1216 if(opt.has_value()) {
1217 detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
1218 return make_optional(monostate{});
1219 }
1220
1221 return optional<monostate>(nullopt);
1222}
1223#else
1224template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())),
1225 detail::enable_if_t<!std::is_void<Ret>::value>* = nullptr>
1226
1227constexpr auto optional_map_impl(Opt&& opt, F&& f) -> optional<Ret> {
1228 return opt.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt)) : optional<Ret>(nullopt);
1229}
1230
1231template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())),
1232 detail::enable_if_t<std::is_void<Ret>::value>* = nullptr>
1233
1234auto optional_map_impl(Opt&& opt, F&& f) -> optional<monostate> {
1235 if(opt.has_value()) {
1236 detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
1237 return monostate{};
1238 }
1239
1240 return nullopt;
1241}
1242#endif
1243} // namespace detail
1244
1247template <class T> class optional<T&> {
1248public:
1249// The different versions for C++14 and 11 are needed because deduced return
1250// types are not SFINAE-safe. This provides better support for things like
1251// generic lambdas. C.f.
1252// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
1253#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
1254
1257 template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) & {
1258 using result = detail::invoke_result_t<F, T&>;
1259 static_assert(detail::is_optional<result>::value, "F must return an optional");
1260
1261 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
1262 }
1263
1264 template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) && {
1265 using result = detail::invoke_result_t<F, T&>;
1266 static_assert(detail::is_optional<result>::value, "F must return an optional");
1267
1268 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
1269 }
1270
1271 template <class F> constexpr auto and_then(F&& f) const& {
1272 using result = detail::invoke_result_t<F, const T&>;
1273 static_assert(detail::is_optional<result>::value, "F must return an optional");
1274
1275 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
1276 }
1277
1278#ifndef TL_OPTIONAL_NO_CONSTRR
1279 template <class F> constexpr auto and_then(F&& f) const&& {
1280 using result = detail::invoke_result_t<F, const T&>;
1281 static_assert(detail::is_optional<result>::value, "F must return an optional");
1282
1283 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
1284 }
1285#endif
1286#else
1289 template <class F> TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&> and_then(F&& f) & {
1290 using result = detail::invoke_result_t<F, T&>;
1291 static_assert(detail::is_optional<result>::value, "F must return an optional");
1292
1293 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
1294 }
1295
1296 template <class F> TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&> and_then(F&& f) && {
1297 using result = detail::invoke_result_t<F, T&>;
1298 static_assert(detail::is_optional<result>::value, "F must return an optional");
1299
1300 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
1301 }
1302
1303 template <class F> constexpr detail::invoke_result_t<F, const T&> and_then(F&& f) const& {
1304 using result = detail::invoke_result_t<F, const T&>;
1305 static_assert(detail::is_optional<result>::value, "F must return an optional");
1306
1307 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
1308 }
1309
1310#ifndef TL_OPTIONAL_NO_CONSTRR
1311 template <class F> constexpr detail::invoke_result_t<F, const T&> and_then(F&& f) const&& {
1312 using result = detail::invoke_result_t<F, const T&>;
1313 static_assert(detail::is_optional<result>::value, "F must return an optional");
1314
1315 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt);
1316 }
1317#endif
1318#endif
1319
1320#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
1322 template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) & { return detail::optional_map_impl(*this, std::forward<F>(f)); }
1323
1324 template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) && {
1325 return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1326 }
1327
1328 template <class F> constexpr auto map(F&& f) const& { return detail::optional_map_impl(*this, std::forward<F>(f)); }
1329
1330 template <class F> constexpr auto map(F&& f) const&& { return detail::optional_map_impl(std::move(*this), std::forward<F>(f)); }
1331#else
1333 template <class F>
1334 TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&>(), std::declval<F&&>())) map(F&& f) & {
1335 return detail::optional_map_impl(*this, std::forward<F>(f));
1336 }
1337
1338 template <class F>
1339 TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&&>(), std::declval<F&&>())) map(F&& f) && {
1340 return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1341 }
1342
1343 template <class F>
1344 constexpr decltype(detail::optional_map_impl(std::declval<const optional&>(), std::declval<F&&>())) map(F&& f) const& {
1345 return detail::optional_map_impl(*this, std::forward<F>(f));
1346 }
1347
1348#ifndef TL_OPTIONAL_NO_CONSTRR
1349 template <class F>
1350 constexpr decltype(detail::optional_map_impl(std::declval<const optional&&>(), std::declval<F&&>())) map(F&& f) const&& {
1351 return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1352 }
1353#endif
1354#endif
1355
1356#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
1358 template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) & { return detail::optional_map_impl(*this, std::forward<F>(f)); }
1359
1360 template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) && {
1361 return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1362 }
1363
1364 template <class F> constexpr auto transform(F&& f) const& { return detail::optional_map_impl(*this, std::forward<F>(f)); }
1365
1366 template <class F> constexpr auto transform(F&& f) const&& { return detail::optional_map_impl(std::move(*this), std::forward<F>(f)); }
1367#else
1369 template <class F>
1370 TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&>(), std::declval<F&&>())) transform(F&& f) & {
1371 return detail::optional_map_impl(*this, std::forward<F>(f));
1372 }
1373
1376 template <class F>
1377 TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&&>(), std::declval<F&&>())) transform(F&& f) && {
1378 return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1379 }
1380
1381 template <class F>
1382 constexpr decltype(detail::optional_map_impl(std::declval<const optional&>(), std::declval<F&&>())) transform(F&& f) const& {
1383 return detail::optional_map_impl(*this, std::forward<F>(f));
1384 }
1385
1386#ifndef TL_OPTIONAL_NO_CONSTRR
1387 template <class F>
1388 constexpr decltype(detail::optional_map_impl(std::declval<const optional&&>(), std::declval<F&&>())) transform(F&& f) const&& {
1389 return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1390 }
1391#endif
1392#endif
1393
1395 template <class F, detail::enable_if_ret_void<F>* = nullptr> optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & {
1396 if(has_value())
1397 return *this;
1398
1399 std::forward<F>(f)();
1400 return nullopt;
1401 }
1402
1403 template <class F, detail::disable_if_ret_void<F>* = nullptr> optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & {
1404 return has_value() ? *this : std::forward<F>(f)();
1405 }
1406
1407 template <class F, detail::enable_if_ret_void<F>* = nullptr> optional<T> or_else(F&& f) && {
1408 if(has_value())
1409 return std::move(*this);
1410
1411 std::forward<F>(f)();
1412 return nullopt;
1413 }
1414
1415 template <class F, detail::disable_if_ret_void<F>* = nullptr> optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) && {
1416 return has_value() ? std::move(*this) : std::forward<F>(f)();
1417 }
1418
1419 template <class F, detail::enable_if_ret_void<F>* = nullptr> optional<T> or_else(F&& f) const& {
1420 if(has_value())
1421 return *this;
1422
1423 std::forward<F>(f)();
1424 return nullopt;
1425 }
1426
1427 template <class F, detail::disable_if_ret_void<F>* = nullptr> optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) const& {
1428 return has_value() ? *this : std::forward<F>(f)();
1429 }
1430
1431#ifndef TL_OPTIONAL_NO_CONSTRR
1432 template <class F, detail::enable_if_ret_void<F>* = nullptr> optional<T> or_else(F&& f) const&& {
1433 if(has_value())
1434 return std::move(*this);
1435
1436 std::forward<F>(f)();
1437 return nullopt;
1438 }
1439
1440 template <class F, detail::disable_if_ret_void<F>* = nullptr> optional<T> or_else(F&& f) const&& {
1441 return has_value() ? std::move(*this) : std::forward<F>(f)();
1442 }
1443#endif
1444
1446 template <class F, class U> U map_or(F&& f, U&& u) & {
1447 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u);
1448 }
1449
1450 template <class F, class U> U map_or(F&& f, U&& u) && {
1451 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u);
1452 }
1453
1454 template <class F, class U> U map_or(F&& f, U&& u) const& {
1455 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u);
1456 }
1457
1458#ifndef TL_OPTIONAL_NO_CONSTRR
1459 template <class F, class U> U map_or(F&& f, U&& u) const&& {
1460 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u);
1461 }
1462#endif
1463
1466 template <class F, class U> detail::invoke_result_t<U> map_or_else(F&& f, U&& u) & {
1467 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)();
1468 }
1469
1470 template <class F, class U> detail::invoke_result_t<U> map_or_else(F&& f, U&& u) && {
1471 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)();
1472 }
1473
1474 template <class F, class U> detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const& {
1475 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)();
1476 }
1477
1478#ifndef TL_OPTIONAL_NO_CONSTRR
1479 template <class F, class U> detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const&& {
1480 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)();
1481 }
1482#endif
1483
1485 template <class U> constexpr optional<typename std::decay<U>::type> conjunction(U&& u) const {
1486 using result = optional<detail::decay_t<U>>;
1487 return has_value() ? result{u} : result{nullopt};
1488 }
1489
1491 TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) & { return has_value() ? *this : rhs; }
1492
1493 constexpr optional disjunction(const optional& rhs) const& { return has_value() ? *this : rhs; }
1494
1495 TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) && { return has_value() ? std::move(*this) : rhs; }
1496
1497#ifndef TL_OPTIONAL_NO_CONSTRR
1498 constexpr optional disjunction(const optional& rhs) const&& { return has_value() ? std::move(*this) : rhs; }
1499#endif
1500
1501 TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) & { return has_value() ? *this : std::move(rhs); }
1502
1503 constexpr optional disjunction(optional&& rhs) const& { return has_value() ? *this : std::move(rhs); }
1504
1505 TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) && { return has_value() ? std::move(*this) : std::move(rhs); }
1506
1507#ifndef TL_OPTIONAL_NO_CONSTRR
1508 constexpr optional disjunction(optional&& rhs) const&& { return has_value() ? std::move(*this) : std::move(rhs); }
1509#endif
1510
1513 optional ret = std::move(*this);
1514 reset();
1515 return ret;
1516 }
1517
1518 using value_type = T&;
1519
1521 constexpr optional() noexcept
1522 : m_value(nullptr) {}
1523
1524 constexpr optional(nullopt_t) noexcept
1525 : m_value(nullptr) {}
1526
1531 TL_OPTIONAL_11_CONSTEXPR optional(const optional& rhs) noexcept = default;
1532
1537 TL_OPTIONAL_11_CONSTEXPR optional(optional&& rhs) = default;
1538
1540 template <class U = T, detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>* = nullptr>
1541 constexpr optional(U&& u) noexcept
1542 : m_value(std::addressof(u)) {
1543 static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue");
1544 }
1545
1546 template <class U>
1547 constexpr explicit optional(const optional<U>& rhs) noexcept
1548 : optional(*rhs) {}
1549
1551 ~optional() = default;
1552
1557 m_value = nullptr;
1558 return *this;
1559 }
1560
1565 optional& operator=(const optional& rhs) = default;
1566
1568 template <class U = T, detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>* = nullptr> optional& operator=(U&& u) {
1569 static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue");
1570 m_value = std::addressof(u);
1571 return *this;
1572 }
1573
1578 template <class U> optional& operator=(const optional<U>& rhs) noexcept {
1579 m_value = std::addressof(rhs.value());
1580 return *this;
1581 }
1582
1584 template <class U = T, detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>* = nullptr>
1585 optional& emplace(U&& u) noexcept {
1586 return *this = std::forward<U>(u);
1587 }
1588
1589 void swap(optional& rhs) noexcept { std::swap(m_value, rhs.m_value); }
1590
1592 constexpr const T* operator->() const noexcept { return m_value; }
1593
1594 TL_OPTIONAL_11_CONSTEXPR T* operator->() noexcept { return m_value; }
1595
1597 TL_OPTIONAL_11_CONSTEXPR T& operator*() noexcept { return *m_value; }
1598
1599 constexpr const T& operator*() const noexcept { return *m_value; }
1600
1601 constexpr bool has_value() const noexcept { return m_value != nullptr; }
1602
1603 constexpr explicit operator bool() const noexcept { return m_value != nullptr; }
1604
1606 TL_OPTIONAL_11_CONSTEXPR T& value() {
1607 if(has_value())
1608 return *m_value;
1609 throw bad_optional_access();
1610 }
1611 TL_OPTIONAL_11_CONSTEXPR const T& value() const {
1612 if(has_value())
1613 return *m_value;
1614 throw bad_optional_access();
1615 }
1616
1618 template <class U> constexpr T value_or(U&& u) const& noexcept {
1619 static_assert(std::is_copy_constructible<T>::value && std::is_convertible<U&&, T>::value,
1620 "T must be copy constructible and convertible from U");
1621 return has_value() ? **this : static_cast<T>(std::forward<U>(u));
1622 }
1623
1625 template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U&& u) && noexcept {
1626 static_assert(std::is_move_constructible<T>::value && std::is_convertible<U&&, T>::value,
1627 "T must be move constructible and convertible from U");
1628 return has_value() ? **this : static_cast<T>(std::forward<U>(u));
1629 }
1630
1632 void reset() noexcept { m_value = nullptr; }
1633
1634private:
1635 T* m_value;
1636}; // namespace tl
1637
1638} // namespace nonstd
1639
1640namespace std {
1641// TODO SFINAE
1642template <class T> struct hash<nonstd::optional<T>> {
1643 ::std::size_t operator()(const nonstd::optional<T>& o) const {
1644 if(!o.has_value())
1645 return 0;
1646
1647 return std::hash<nonstd::detail::remove_const_t<T>>()(*o);
1648 }
1649};
1650} // namespace std
1651
1652#endif
1653#endif
Used to represent an optional with no data; essentially a bool.
Definition optional.hpp:103
TL_OPTIONAL_11_CONSTEXPR T & value()
Returns the contained value if there is one, otherwise throws bad_optional_access.
optional< T > TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) &
Calls f if the optional is empty.
optional & operator=(nullopt_t) noexcept
TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) &&noexcept
\group value_or
detail::invoke_result_t< U > map_or_else(F &&f, U &&u) &
optional & operator=(const optional< U > &rhs) noexcept
optional & operator=(U &&u)
Rebinds this optional to u.
TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) &
Returns rhs if *this is empty, otherwise the current value.
TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval< optional && >(), std::declval< F && >())) transform(F &&f) &&
constexpr const T * operator->() const noexcept
Returns a pointer to the stored value.
TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval< optional & >(), std::declval< F && >())) transform(F &&f) &
Carries out some operation on the stored object if there is one.
constexpr optional< typename std::decay< U >::type > conjunction(U &&u) const
Returns u if *this has a value, otherwise an empty optional.
optional & operator=(const optional &rhs)=default
TL_OPTIONAL_11_CONSTEXPR optional(optional &&rhs)=default
TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval< optional & >(), std::declval< F && >())) map(F &&f) &
Carries out some operation on the stored object if there is one.
constexpr optional(U &&u) noexcept
Constructs the stored value with u.
TL_OPTIONAL_11_CONSTEXPR T & operator*() noexcept
Returns the stored value.
constexpr T value_or(U &&u) const &noexcept
Returns the stored value if there is one, otherwise returns u.
TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t< F, T & > and_then(F &&f) &
optional take()
Takes the value out of the optional, leaving it empty.
~optional()=default
No-op.
U map_or(F &&f, U &&u) &
Maps the stored value with f if there is one, otherwise returns u.
optional & emplace(U &&u) noexcept
Rebinds this optional to u.
constexpr optional() noexcept
Constructs an optional that does not contain a value.
void reset() noexcept
Destroys the stored value if one exists, making the optional empty.
TL_OPTIONAL_11_CONSTEXPR optional(const optional &rhs) noexcept=default
constexpr const T * operator->() const
Returns a pointer to the stored value.
optional(optional< U > &&rhs)
Converting move constructor.
Definition optional.hpp:904
void swap(optional &rhs) noexcept(std::is_nothrow_move_constructible< T >::value &&detail::is_nothrow_swappable< T >::value)
TL_OPTIONAL_11_CONSTEXPR optional(const optional &rhs)=default
optional & operator=(const optional< U > &rhs)
Definition optional.hpp:960
constexpr T value_or(U &&u) const &
Returns the stored value if there is one, otherwise returns u.
void reset() noexcept
Destroys the stored value if one exists, making the optional empty.
U map_or(F &&f, U &&u) &
Maps the stored value with f if there is one, otherwise returns u.
Definition optional.hpp:771
T & emplace(Args &&... args)
Definition optional.hpp:999
TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval< optional & >(), std::declval< F && >())) map(F &&f) &
Carries out some operation on the stored object if there is one.
Definition optional.hpp:667
constexpr optional() noexcept=default
Constructs an optional that does not contain a value.
optional & operator=(optional< U > &&rhs)
Definition optional.hpp:981
TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t< F, T & > and_then(F &&f) &
Definition optional.hpp:625
constexpr optional< typename std::decay< U >::type > conjunction(U &&u) const
Returns u if *this has a value, otherwise an empty optional.
Definition optional.hpp:810
TL_OPTIONAL_11_CONSTEXPR optional(optional &&rhs)=default
TL_OPTIONAL_11_CONSTEXPR T & value() &
Returns the contained value if there is one, otherwise throws bad_optional_access.
optional & operator=(optional &&rhs)=default
optional & operator=(const optional &rhs)=default
optional & operator=(U &&u)
Definition optional.hpp:946
TL_OPTIONAL_11_CONSTEXPR T & operator*() &
Returns the stored value.
optional< T > TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) &
Calls f if the optional is empty.
Definition optional.hpp:720
detail::invoke_result_t< U > map_or_else(F &&f, U &&u) &
Definition optional.hpp:791
optional(const optional< U > &rhs)
Converting copy constructor.
Definition optional.hpp:888
TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval< optional & >(), std::declval< F && >())) transform(F &&f) &
Carries out some operation on the stored object if there is one.
Definition optional.hpp:698
optional take()
Takes the value out of the optional, leaving it empty.
Definition optional.hpp:837
~optional()=default
Destroys the stored value if there is one.
TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) &
Returns rhs if *this is empty, otherwise the current value.
Definition optional.hpp:816
constexpr optional(U &&u)
Constructs the stored value with u.
Definition optional.hpp:877
constexpr optional(detail::enable_if_t< std::is_constructible< T, Args... >::value, in_place_t >, Args &&... args)
Constructs the stored value in-place using the given arguments.
Definition optional.hpp:864
constexpr bool has_value() const noexcept
Returns whether or not the optional has a value.
optional & operator=(nullopt_t) noexcept
Definition optional.hpp:923
A tag type to tell optional to construct its value in-place.
Definition optional.hpp:106
A tag type to represent an empty optional.
Definition optional.hpp:557