17 #ifndef TL_OPTIONAL_HPP
18 #define TL_OPTIONAL_HPP
20 #define TL_OPTIONAL_VERSION_MAJOR 1
21 #define TL_OPTIONAL_VERSION_MINOR 0
22 #define TL_OPTIONAL_VERSION_PATCH 0
27 #include <type_traits>
30 #if (defined(_MSC_VER) && _MSC_VER == 1900)
31 #define TL_OPTIONAL_MSVC2015
34 #if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \
36 #define TL_OPTIONAL_GCC49
39 #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && \
41 #define TL_OPTIONAL_GCC54
44 #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && \
46 #define TL_OPTIONAL_GCC55
49 #if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \
52 #define TL_OPTIONAL_NO_CONSTRR
55 #define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
56 std::has_trivial_copy_constructor<T>::value
57 #define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign<T>::value
60 #define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
64 #elif (defined(__GNUC__) && __GNUC__ < 8 && \
66 #ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
67 #define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
71 struct is_trivially_copy_constructible : std::is_trivially_copy_constructible<T>{};
72 #ifdef _GLIBCXX_VECTOR
73 template<
class T,
class A>
74 struct is_trivially_copy_constructible<
std::vector<T,A>>
75 : std::is_trivially_copy_constructible<T>{};
81 #define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
82 tl::detail::is_trivially_copy_constructible<T>::value
83 #define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
84 std::is_trivially_copy_assignable<T>::value
85 #define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
87 #define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
88 std::is_trivially_copy_constructible<T>::value
89 #define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
90 std::is_trivially_copy_assignable<T>::value
91 #define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
94 #if __cplusplus > 201103L
95 #define TL_OPTIONAL_CXX14
99 #if (__cplusplus == 201103L || defined(TL_OPTIONAL_MSVC2015) || \
100 defined(TL_OPTIONAL_GCC49))
101 #define TL_OPTIONAL_11_CONSTEXPR
103 #define TL_OPTIONAL_11_CONSTEXPR constexpr
107 #ifndef TL_MONOSTATE_INPLACE_MUTEX
108 #define TL_MONOSTATE_INPLACE_MUTEX
123 #ifndef TL_TRAITS_MUTEX
124 #define TL_TRAITS_MUTEX
130 template <
bool E,
class T =
void>
132 template <
bool B,
class T,
class F>
138 template <
class B,
class... Bs>
140 : std::conditional<bool(B::value), conjunction<Bs...>, B>
::type {};
142 #if defined(_LIBCPP_VERSION) && __cplusplus == 201103L
143 #define TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
149 #ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
150 template <
class T>
struct is_pointer_to_non_const_member_func : std::false_type{};
151 template <
class T,
class Ret,
class... Args>
152 struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...)> : std::true_type{};
153 template <
class T,
class Ret,
class... Args>
154 struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...)&> : std::true_type{};
155 template <
class T,
class Ret,
class... Args>
156 struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...)&&> : std::true_type{};
157 template <
class T,
class Ret,
class... Args>
158 struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...) volatile> : std::true_type{};
159 template <
class T,
class Ret,
class... Args>
160 struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...) volatile&> : std::true_type{};
161 template <
class T,
class Ret,
class... Args>
162 struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...) volatile&&> : std::true_type{};
164 template <
class T>
struct is_const_or_const_ref : std::false_type{};
165 template <
class T>
struct is_const_or_const_ref<T const&> : std::true_type{};
166 template <
class T>
struct is_const_or_const_ref<T const> : std::true_type{};
171 template <
typename Fn,
typename... Args,
172 #ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
173 typename =
enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value
174 && is_const_or_const_ref<Args...>::value)>,
176 typename =
enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>,
178 constexpr
auto invoke(Fn &&f, Args &&... args) noexcept(
179 noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
180 -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {
181 return std::mem_fn(f)(std::forward<Args>(args)...);
184 template <
typename Fn,
typename... Args,
185 typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>>
186 constexpr
auto invoke(Fn &&f, Args &&... args) noexcept(
187 noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
188 -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {
189 return std::forward<Fn>(f)(std::forward<Args>(args)...);
195 template <
class F,
class... Us>
197 F, decltype(detail::
invoke(std::declval<F>(), std::declval<Us>()...), void()),
202 template <
class F,
class... Us>
205 template <
class F,
class... Us>
208 #if defined(_MSC_VER) && _MSC_VER <= 1900
210 template <
class T,
class U = T>
struct is_swappable : std::true_type {};
212 template <
class T,
class U = T>
struct is_nothrow_swappable : std::true_type {};
215 namespace swap_adl_tests {
220 template <
class T>
tag swap(T &, T &);
221 template <
class T, std::
size_t N>
tag swap(T (&a)[N], T (&b)[N]);
225 template <
class,
class> std::false_type
can_swap(...) noexcept(false);
226 template <class T, class U,
227 class = decltype(
swap(
std::declval<T &>(),
std::declval<U &>()))>
229 std::declval<U &>())));
231 template <class, class>
std::false_type
uses_std(...);
232 template <class T, class U>
238 :
std::integral_constant<
bool,
239 std::is_nothrow_move_constructible<T>::value &&
240 std::is_nothrow_move_assignable<T>::value> {};
242 template <
class T, std::
size_t N>
245 template <
class T,
class U>
247 : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};
250 template <
class T,
class U = T>
252 : std::integral_constant<
254 decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
255 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
256 (std::is_move_assignable<T>::value &&
257 std::is_move_constructible<T>::value))> {};
259 template <
class T, std::
size_t N>
261 : std::integral_constant<
263 decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
265 detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value ||
266 is_swappable<T, T>::value)> {};
268 template <
class T,
class U = T>
270 : std::integral_constant<
272 is_swappable<T, U>::value &&
273 ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value
274 &&detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||
275 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
276 detail::swap_adl_tests::is_adl_swap_noexcept<T,
295 template <
class F,
class U,
class = invoke_result_t<F, U>>
300 template <
class F,
class... U>
302 : std::is_void<invoke_result_t<F, U...>> {};
303 template <
class F,
class... U>
306 template <
class T,
class... U>
309 template <
class T,
class... U>
312 template <
class T,
class U>
315 !std::is_same<detail::decay_t<U>,
in_place_t>::value &&
318 template <
class T,
class U,
class Other>
320 std::is_constructible<T, Other>::value &&
321 !std::is_constructible<T, optional<U> &>::value &&
322 !std::is_constructible<T, optional<U> &&>::value &&
323 !std::is_constructible<T, const optional<U> &>::value &&
324 !std::is_constructible<T, const optional<U> &&>::value &&
325 !std::is_convertible<optional<U> &, T>::value &&
326 !std::is_convertible<optional<U> &&, T>::value &&
327 !std::is_convertible<const optional<U> &, T>::value &&
328 !std::is_convertible<const optional<U> &&, T>::value>;
330 template <
class T,
class U>
334 std::is_same<T, detail::decay_t<U>>>::value &&
335 std::is_constructible<T, U>::value && std::is_assignable<T &, U>::value>;
337 template <
class T,
class U,
class Other>
339 std::is_constructible<T, Other>::value &&
340 std::is_assignable<T &, Other>::value &&
341 !std::is_constructible<T, optional<U> &>::value &&
342 !std::is_constructible<T, optional<U> &&>::value &&
343 !std::is_constructible<T, const optional<U> &>::value &&
344 !std::is_constructible<T, const optional<U> &&>::value &&
345 !std::is_convertible<optional<U> &, T>::value &&
346 !std::is_convertible<optional<U> &&, T>::value &&
347 !std::is_convertible<const optional<U> &, T>::value &&
348 !std::is_convertible<const optional<U> &&, T>::value &&
349 !std::is_assignable<T &, optional<U> &>::value &&
350 !std::is_assignable<T &, optional<U> &&>::value &&
351 !std::is_assignable<T &, const optional<U> &>::value &&
352 !std::is_assignable<T &, const optional<U> &&>::value>;
357 template <class T, bool = ::std::is_trivially_destructible<T>::value>
362 template <
class... U>
387 template <
class... U>
412 template <
class... Args>
void construct(Args &&... args) noexcept {
413 new (std::addressof(this->
m_value)) T(std::forward<Args>(args)...);
417 template <
class Opt>
void assign(Opt &&rhs) {
419 if (rhs.has_value()) {
420 this->
m_value = std::forward<Opt>(rhs).get();
427 else if (rhs.has_value()) {
437 #ifndef TL_OPTIONAL_NO_CONSTRR
438 constexpr
const T &&
get() const && {
return std::move(this->
m_value); }
444 template <
class T,
bool = TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>
473 #ifndef TL_OPTIONAL_GCC49
474 template <class T, bool = std::is_trivially_move_constructible<T>::value>
488 std::is_nothrow_move_constructible<T>::value) {
528 #ifndef TL_OPTIONAL_GCC49
529 template <class T, bool = std::is_trivially_destructible<T>::value
530 &&std::is_trivially_move_constructible<T>::value
531 &&std::is_trivially_move_assignable<T>::value>
553 std::is_nothrow_move_constructible<T>::value
554 &&std::is_nothrow_move_assignable<T>::value) {
555 this->
assign(std::move(rhs));
562 template <class T, bool EnableCopy = std::is_copy_constructible<T>::value,
563 bool EnableMove = std::is_move_constructible<T>::value>
607 bool EnableCopy = (std::is_copy_constructible<T>::value &&
608 std::is_copy_assignable<T>::value),
609 bool EnableMove = (std::is_move_constructible<T>::value &&
610 std::is_move_assignable<T>::value)>
669 const char *
what() const noexcept {
return "Optional has no value"; }
679 class optional :
private detail::optional_move_assign_base<T>,
680 private detail::optional_delete_ctor_base<T>,
681 private detail::optional_delete_assign_base<T> {
684 static_assert(!std::is_same<T, in_place_t>::value,
685 "instantiation of optional with in_place_t is ill-formed");
687 "instantiation of optional with nullopt_t is ill-formed");
694 #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
695 !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
701 "F must return an optional");
710 "F must return an optional");
716 template <
class F> constexpr
auto and_then(F &&f)
const & {
717 using result = detail::invoke_result_t<F, const T &>;
718 static_assert(detail::is_optional<result>::value,
719 "F must return an optional");
725 #ifndef TL_OPTIONAL_NO_CONSTRR
726 template <
class F> constexpr
auto and_then(F &&f)
const && {
727 using result = detail::invoke_result_t<F, const T &&>;
728 static_assert(detail::is_optional<result>::value,
729 "F must return an optional");
742 "F must return an optional");
752 "F must return an optional");
762 "F must return an optional");
768 #ifndef TL_OPTIONAL_NO_CONSTRR
773 "F must return an optional");
781 #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
782 !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
792 template <
class F> constexpr
auto map(F &&f)
const & {
796 template <
class F> constexpr
auto map(F &&f)
const && {
803 std::declval<F &&>()))
810 std::declval<F &&>()))
817 std::declval<F &&>()))
822 #ifndef TL_OPTIONAL_NO_CONSTRR
825 std::declval<F &&>()))
832 #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
833 !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
843 template <
class F> constexpr
auto transform(F&& f)
const & {
847 template <
class F> constexpr
auto transform(F&& f)
const && {
854 std::declval<F&&>()))
861 std::declval<F&&>()))
868 std::declval<F&&>()))
873 #ifndef TL_OPTIONAL_NO_CONSTRR
876 std::declval<F&&>()))
884 template <
class F, detail::enable_if_ret_
void<F> * =
nullptr>
889 std::forward<F>(f)();
893 template <
class F, detail::disable_if_ret_
void<F> * =
nullptr>
895 return has_value() ? *this : std::forward<F>(f)();
898 template <
class F, detail::enable_if_ret_
void<F> * =
nullptr>
901 return std::move(*
this);
903 std::forward<F>(f)();
907 template <
class F, detail::disable_if_ret_
void<F> * =
nullptr>
909 return has_value() ? std::move(*
this) : std::forward<F>(f)();
912 template <
class F, detail::enable_if_ret_
void<F> * =
nullptr>
917 std::forward<F>(f)();
921 template <
class F, detail::disable_if_ret_
void<F> * =
nullptr>
923 return has_value() ? *this : std::forward<F>(f)();
926 #ifndef TL_OPTIONAL_NO_CONSTRR
927 template <
class F, detail::enable_if_ret_
void<F> * =
nullptr>
930 return std::move(*
this);
932 std::forward<F>(f)();
936 template <
class F, detail::disable_if_ret_
void<F> * =
nullptr>
938 return has_value() ? std::move(*
this) : std::forward<F>(f)();
943 template <
class F,
class U> U
map_or(F &&f, U &&u) & {
945 : std::forward<U>(u);
948 template <
class F,
class U> U
map_or(F &&f, U &&u) && {
950 : std::forward<U>(u);
953 template <
class F,
class U> U
map_or(F &&f, U &&u)
const & {
955 : std::forward<U>(u);
958 #ifndef TL_OPTIONAL_NO_CONSTRR
959 template <
class F,
class U> U
map_or(F &&f, U &&u)
const && {
961 : std::forward<U>(u);
967 template <
class F,
class U>
970 : std::forward<U>(u)();
973 template <
class F,
class U>
976 : std::forward<U>(u)();
979 template <
class F,
class U>
982 : std::forward<U>(u)();
985 #ifndef TL_OPTIONAL_NO_CONSTRR
986 template <
class F,
class U>
989 : std::forward<U>(u)();
1010 return has_value() ? std::move(*
this) : rhs;
1013 #ifndef TL_OPTIONAL_NO_CONSTRR
1015 return has_value() ? std::move(*
this) : rhs;
1020 return has_value() ? *this : std::move(rhs);
1024 return has_value() ? *this : std::move(rhs);
1028 return has_value() ? std::move(*
this) : std::move(rhs);
1031 #ifndef TL_OPTIONAL_NO_CONSTRR
1033 return has_value() ? std::move(*
this) : std::move(rhs);
1047 constexpr
optional() noexcept = default;
1064 template <
class... Args>
1070 template <
class U,
class... Args>
1075 std::initializer_list<U> il, Args &&... args) {
1076 this->construct(il, std::forward<Args>(args)...);
1097 if (rhs.has_value()) {
1098 this->construct(*rhs);
1102 template <
class U, detail::enable_from_other<T, U, const U &> * =
nullptr,
1103 detail::enable_if_t<!std::is_convertible<const U &, T>::value> * =
1106 if (rhs.has_value()) {
1107 this->construct(*rhs);
1116 if (rhs.has_value()) {
1117 this->construct(std::move(*rhs));
1125 if (rhs.has_value()) {
1126 this->construct(std::move(*rhs));
1139 this->m_has_value =
false;
1159 template <
class U = T, detail::enable_assign_forward<T, U> * =
nullptr>
1162 this->m_value = std::forward<U>(u);
1164 this->construct(std::forward<U>(u));
1178 if (rhs.has_value()) {
1179 this->m_value = *rhs;
1185 if (rhs.has_value()) {
1186 this->construct(*rhs);
1197 template <
class U, detail::enable_assign_from_other<T, U, U> * =
nullptr>
1200 if (rhs.has_value()) {
1201 this->m_value = std::move(*rhs);
1207 if (rhs.has_value()) {
1208 this->construct(std::move(*rhs));
1216 template <
class... Args> T &
emplace(Args &&... args) {
1217 static_assert(std::is_constructible<T, Args &&...>::value,
1218 "T must be constructible with Args");
1221 this->construct(std::forward<Args>(args)...);
1225 template <
class U,
class... Args>
1227 std::is_constructible<T, std::initializer_list<U> &, Args &&...>
::value,
1229 emplace(std::initializer_list<U> il, Args &&... args) {
1231 this->construct(il, std::forward<Args>(args)...);
1246 if (rhs.has_value()) {
1249 new (std::addressof(rhs.m_value)) T(std::move(this->m_value));
1250 this->m_value.T::~T();
1252 }
else if (rhs.has_value()) {
1253 new (std::addressof(this->m_value)) T(std::move(rhs.m_value));
1254 rhs.m_value.T::~T();
1256 swap(this->m_has_value, rhs.m_has_value);
1261 return std::addressof(this->m_value);
1265 return std::addressof(this->m_value);
1271 constexpr
const T &
operator*() const & {
return this->m_value; }
1274 return std::move(this->m_value);
1277 #ifndef TL_OPTIONAL_NO_CONSTRR
1278 constexpr
const T &&
operator*() const && {
return std::move(this->m_value); }
1282 constexpr
bool has_value() const noexcept {
return this->m_has_value; }
1284 constexpr
explicit operator bool() const noexcept {
1285 return this->m_has_value;
1291 return this->m_value;
1296 return this->m_value;
1301 return std::move(this->m_value);
1305 #ifndef TL_OPTIONAL_NO_CONSTRR
1308 return std::move(this->m_value);
1314 template <
class U> constexpr T
value_or(U &&u)
const & {
1315 static_assert(std::is_copy_constructible<T>::value &&
1316 std::is_convertible<U &&, T>::value,
1317 "T must be copy constructible and convertible from U");
1318 return has_value() ? **this :
static_cast<T
>(std::forward<U>(u));
1322 static_assert(std::is_move_constructible<T>::value &&
1323 std::is_convertible<U &&, T>::value,
1324 "T must be move constructible and convertible from U");
1325 return has_value() ? **this :
static_cast<T
>(std::forward<U>(u));
1332 this->m_has_value =
false;
1338 template <
class T,
class U>
1341 return lhs.has_value() == rhs.has_value() &&
1342 (!lhs.has_value() || *lhs == *rhs);
1344 template <
class T,
class U>
1347 return lhs.has_value() != rhs.has_value() ||
1348 (lhs.has_value() && *lhs != *rhs);
1350 template <
class T,
class U>
1353 return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs);
1355 template <
class T,
class U>
1358 return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs);
1360 template <
class T,
class U>
1363 return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs);
1365 template <
class T,
class U>
1368 return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs);
1374 return !lhs.has_value();
1378 return !rhs.has_value();
1382 return lhs.has_value();
1386 return rhs.has_value();
1394 return rhs.has_value();
1398 return !lhs.has_value();
1406 return lhs.has_value();
1418 return !rhs.has_value();
1422 template <
class T,
class U>
1424 return lhs.has_value() ? *lhs == rhs :
false;
1426 template <
class T,
class U>
1428 return rhs.has_value() ? lhs == *rhs :
false;
1430 template <
class T,
class U>
1432 return lhs.has_value() ? *lhs != rhs :
true;
1434 template <
class T,
class U>
1436 return rhs.has_value() ? lhs != *rhs :
true;
1438 template <
class T,
class U>
1440 return lhs.has_value() ? *lhs < rhs :
true;
1442 template <
class T,
class U>
1444 return rhs.has_value() ? lhs < *rhs :
false;
1446 template <
class T,
class U>
1448 return lhs.has_value() ? *lhs <= rhs :
true;
1450 template <
class T,
class U>
1452 return rhs.has_value() ? lhs <= *rhs :
false;
1454 template <
class T,
class U>
1456 return lhs.has_value() ? *lhs > rhs :
false;
1458 template <
class T,
class U>
1460 return rhs.has_value() ? lhs > *rhs :
true;
1462 template <
class T,
class U>
1464 return lhs.has_value() ? *lhs >= rhs :
false;
1466 template <
class T,
class U>
1468 return rhs.has_value() ? lhs >= *rhs :
true;
1472 detail::enable_if_t<std::is_move_constructible<T>::value> * =
nullptr,
1473 detail::enable_if_t<detail::is_swappable<T>::value> * =
nullptr>
1475 optional<T> &rhs) noexcept(noexcept(lhs.swap(rhs))) {
1476 return lhs.swap(rhs);
1491 template <
class T,
class... Args>
1495 template <
class T,
class U,
class... Args>
1501 #if __cplusplus >= 201703L
1502 template <
class T> optional(T)->optional<T>;
1507 #ifdef TL_OPTIONAL_CXX14
1508 template <
class Opt,
class F,
1510 *std::declval<Opt>())),
1511 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
1513 return opt.has_value()
1518 template <
class Opt,
class F,
1520 *std::declval<Opt>())),
1521 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
1523 if (opt.has_value()) {
1528 return optional<monostate>(
nullopt);
1531 template <
class Opt,
class F,
1533 *std::declval<Opt>())),
1534 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
1542 template <
class Opt,
class F,
1544 *std::declval<Opt>())),
1548 if (opt.has_value()) {
1566 #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
1567 !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
1574 "F must return an optional");
1583 "F must return an optional");
1589 template <
class F> constexpr
auto and_then(F &&f)
const & {
1592 "F must return an optional");
1598 #ifndef TL_OPTIONAL_NO_CONSTRR
1599 template <
class F> constexpr
auto and_then(F &&f)
const && {
1602 "F must return an optional");
1615 "F must return an optional");
1625 "F must return an optional");
1635 "F must return an optional");
1641 #ifndef TL_OPTIONAL_NO_CONSTRR
1646 "F must return an optional");
1654 #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
1655 !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
1665 template <
class F> constexpr
auto map(F &&f)
const & {
1669 template <
class F> constexpr
auto map(F &&f)
const && {
1676 std::declval<F &&>()))
1683 std::declval<F &&>()))
1690 std::declval<F &&>()))
1695 #ifndef TL_OPTIONAL_NO_CONSTRR
1698 std::declval<F &&>()))
1705 #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
1706 !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
1716 template <
class F> constexpr
auto transform(F&& f)
const & {
1720 template <
class F> constexpr
auto transform(F&& f)
const && {
1727 std::declval<F&&>()))
1736 std::declval<F&&>()))
1743 std::declval<F&&>()))
1748 #ifndef TL_OPTIONAL_NO_CONSTRR
1751 std::declval<F&&>()))
1759 template <
class F, detail::enable_if_ret_
void<F> * =
nullptr>
1764 std::forward<F>(f)();
1768 template <
class F, detail::disable_if_ret_
void<F> * =
nullptr>
1770 return has_value() ? *this : std::forward<F>(f)();
1773 template <
class F, detail::enable_if_ret_
void<F> * =
nullptr>
1776 return std::move(*
this);
1778 std::forward<F>(f)();
1782 template <
class F, detail::disable_if_ret_
void<F> * =
nullptr>
1784 return has_value() ? std::move(*
this) : std::forward<F>(f)();
1787 template <
class F, detail::enable_if_ret_
void<F> * =
nullptr>
1792 std::forward<F>(f)();
1796 template <
class F, detail::disable_if_ret_
void<F> * =
nullptr>
1798 return has_value() ? *this : std::forward<F>(f)();
1801 #ifndef TL_OPTIONAL_NO_CONSTRR
1802 template <
class F, detail::enable_if_ret_
void<F> * =
nullptr>
1805 return std::move(*
this);
1807 std::forward<F>(f)();
1811 template <
class F, detail::disable_if_ret_
void<F> * =
nullptr>
1813 return has_value() ? std::move(*
this) : std::forward<F>(f)();
1818 template <
class F,
class U> U
map_or(F &&f, U &&u) & {
1820 : std::forward<U>(u);
1823 template <
class F,
class U> U
map_or(F &&f, U &&u) && {
1824 return has_value() ?
detail::invoke(std::forward<F>(f), std::move(**
this))
1825 : std::forward<U>(u);
1828 template <
class F,
class U> U
map_or(F &&f, U &&u)
const & {
1830 : std::forward<U>(u);
1833 #ifndef TL_OPTIONAL_NO_CONSTRR
1834 template <
class F,
class U> U
map_or(F &&f, U &&u)
const && {
1835 return has_value() ?
detail::invoke(std::forward<F>(f), std::move(**
this))
1836 : std::forward<U>(u);
1842 template <
class F,
class U>
1845 : std::forward<U>(u)();
1848 template <
class F,
class U>
1850 return has_value() ?
detail::invoke(std::forward<F>(f), std::move(**
this))
1851 : std::forward<U>(u)();
1854 template <
class F,
class U>
1857 : std::forward<U>(u)();
1860 #ifndef TL_OPTIONAL_NO_CONSTRR
1861 template <
class F,
class U>
1863 return has_value() ?
detail::invoke(std::forward<F>(f), std::move(**
this))
1864 : std::forward<U>(u)();
1872 return has_value() ? result{u} : result{
nullopt};
1877 return has_value() ? *this : rhs;
1881 return has_value() ? *this : rhs;
1885 return has_value() ? std::move(*
this) : rhs;
1888 #ifndef TL_OPTIONAL_NO_CONSTRR
1890 return has_value() ? std::move(*
this) : rhs;
1895 return has_value() ? *this : std::move(rhs);
1899 return has_value() ? *this : std::move(rhs);
1903 return has_value() ? std::move(*
this) : std::move(rhs);
1906 #ifndef TL_OPTIONAL_NO_CONSTRR
1908 return has_value() ? std::move(*
this) : std::move(rhs);
1939 template <
class U = T,
1942 constexpr
optional(U &&u) noexcept : m_value(std::addressof(u)) {
1943 static_assert(std::is_lvalue_reference<U>::value,
"U must be an lvalue");
1967 template <
class U = T,
1971 static_assert(std::is_lvalue_reference<U>::value,
"U must be an lvalue");
1972 m_value = std::addressof(u);
1981 m_value = std::addressof(rhs.value());
1986 template <
class U = T,
1990 return *
this = std::forward<U>(u);
1996 constexpr
const T *
operator->() const noexcept {
return m_value; }
2003 constexpr
const T &
operator*() const noexcept {
return *m_value; }
2005 constexpr
bool has_value() const noexcept {
return m_value !=
nullptr; }
2007 constexpr
explicit operator bool() const noexcept {
2008 return m_value !=
nullptr;
2024 template <
class U> constexpr T
value_or(U &&u)
const & noexcept {
2025 static_assert(std::is_copy_constructible<T>::value &&
2026 std::is_convertible<U &&, T>::value,
2027 "T must be copy constructible and convertible from U");
2028 return has_value() ? **this :
static_cast<T
>(std::forward<U>(u));
2033 static_assert(std::is_move_constructible<T>::value &&
2034 std::is_convertible<U &&, T>::value,
2035 "T must be move constructible and convertible from U");
2036 return has_value() ? **this :
static_cast<T
>(std::forward<U>(u));
2040 void reset() noexcept { m_value =
nullptr; }
2052 template <
class T>
struct hash<
tl::optional<T>> {
2057 return std::hash<tl::detail::remove_const_t<T>>()(*o);