mirror of
https://github.com/TartanLlama/optional.git
synced 2025-07-30 09:57:13 +02:00
Clang format, support cohabitation with tl::expected
This commit is contained in:
673
optional.hpp
673
optional.hpp
@ -72,112 +72,115 @@
|
||||
#define TL_OPTIONAL_11_CONSTEXPR constexpr
|
||||
#endif
|
||||
|
||||
namespace tl {
|
||||
/// \brief Used to represent an optional with no data; essentially a bool
|
||||
class monostate {};
|
||||
namespace tl {
|
||||
#ifndef TL_OPTIONAL_EXPECTED_MUTEX
|
||||
/// \brief Used to represent an optional with no data; essentially a bool
|
||||
class monostate {};
|
||||
|
||||
/// \brief A tag type to tell optional to construct its value in-place
|
||||
struct in_place_t {
|
||||
/// \brief A tag type to tell optional to construct its value in-place
|
||||
struct in_place_t {
|
||||
explicit in_place_t() = default;
|
||||
};
|
||||
/// \brief A tag to tell optional to construct its value in-place
|
||||
static constexpr in_place_t in_place{};
|
||||
};
|
||||
/// \brief A tag to tell optional to construct its value in-place
|
||||
static constexpr in_place_t in_place{};
|
||||
#endif
|
||||
|
||||
template <class T> class optional;
|
||||
template <class T> class optional;
|
||||
|
||||
/// \exclude
|
||||
namespace detail {
|
||||
/// \exclude
|
||||
namespace detail {
|
||||
#ifndef TL_OPTIONAL_EXPECTED_MUTEX
|
||||
// C++14-style aliases for brevity
|
||||
template <class T> using remove_const_t = typename std::remove_const<T>::type;
|
||||
template <class T>
|
||||
using remove_reference_t = typename std::remove_reference<T>::type;
|
||||
template <class T> using decay_t = typename std::decay<T>::type;
|
||||
template <bool E, class T = void>
|
||||
using enable_if_t = typename std::enable_if<E, T>::type;
|
||||
template <bool B, class T, class F>
|
||||
using conditional_t = typename std::conditional<B, T, F>::type;
|
||||
|
||||
// C++14-style aliases for brevity
|
||||
template <class T> using remove_const_t = typename std::remove_const<T>::type;
|
||||
template <class T>
|
||||
using remove_reference_t = typename std::remove_reference<T>::type;
|
||||
template <class T> using decay_t = typename std::decay<T>::type;
|
||||
template <bool E, class T = void>
|
||||
using enable_if_t = typename std::enable_if<E, T>::type;
|
||||
template <bool B, class T, class F>
|
||||
using conditional_t = typename std::conditional<B, T, F>::type;
|
||||
|
||||
// std::conjunction from C++17
|
||||
template <class...> struct conjunction : std::true_type {};
|
||||
template <class B> struct conjunction<B> : B {};
|
||||
template <class B, class... Bs>
|
||||
struct conjunction<B, Bs...>
|
||||
// std::conjunction from C++17
|
||||
template <class...> struct conjunction : std::true_type {};
|
||||
template <class B> struct conjunction<B> : B {};
|
||||
template <class B, class... Bs>
|
||||
struct conjunction<B, Bs...>
|
||||
: std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};
|
||||
|
||||
// std::void_t from C++17
|
||||
template <class...> struct voider { using type = void; };
|
||||
template <class... Ts> using void_t = typename voider<Ts...>::type;
|
||||
|
||||
// Trait for checking if a type is a tl::optional
|
||||
template <class T> struct is_optional_impl : std::false_type {};
|
||||
template <class T> struct is_optional_impl<optional<T>> : std::true_type {};
|
||||
template <class T> using is_optional = is_optional_impl<decay_t<T>>;
|
||||
|
||||
// std::invoke from C++17
|
||||
// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround
|
||||
template <typename Fn, typename... Args,
|
||||
// std::invoke from C++17
|
||||
// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround
|
||||
template <typename Fn, typename... Args,
|
||||
typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>{}>,
|
||||
int = 0>
|
||||
constexpr auto invoke(Fn &&f, Args &&... args) noexcept(
|
||||
constexpr auto invoke(Fn &&f, Args &&... args) noexcept(
|
||||
noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
|
||||
-> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {
|
||||
return std::mem_fn(f)(std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Fn, typename... Args,
|
||||
template <typename Fn, typename... Args,
|
||||
typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>{}>>
|
||||
constexpr auto invoke(Fn &&f, Args &&... args) noexcept(
|
||||
constexpr auto invoke(Fn &&f, Args &&... args) noexcept(
|
||||
noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
|
||||
-> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {
|
||||
return std::forward<Fn>(f)(std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
// std::invoke_result from C++17
|
||||
template <class F, class, class... Us> struct invoke_result_impl;
|
||||
// std::invoke_result from C++17
|
||||
template <class F, class, class... Us> struct invoke_result_impl;
|
||||
|
||||
template <class F, class... Us>
|
||||
struct invoke_result_impl<
|
||||
template <class F, class... Us>
|
||||
struct invoke_result_impl<
|
||||
F, decltype(invoke(std::declval<F>(), std::declval<Us>()...), void()),
|
||||
Us...> {
|
||||
using type = decltype(invoke(std::declval<F>(), std::declval<Us>()...));
|
||||
};
|
||||
};
|
||||
|
||||
template <class F, class... Us>
|
||||
using invoke_result = invoke_result_impl<F, void, Us...>;
|
||||
template <class F, class... Us>
|
||||
using invoke_result = invoke_result_impl<F, void, Us...>;
|
||||
|
||||
template <class F, class... Us>
|
||||
using invoke_result_t = typename invoke_result<F, Us...>::type;
|
||||
template <class F, class... Us>
|
||||
using invoke_result_t = typename invoke_result<F, Us...>::type;
|
||||
#endif
|
||||
|
||||
// Change void to tl::monostate
|
||||
template <class U>
|
||||
using fixup_void = conditional_t<std::is_void<U>::value, monostate, U>;
|
||||
// std::void_t from C++17
|
||||
template <class...> struct voider { using type = void; };
|
||||
template <class... Ts> using void_t = typename voider<Ts...>::type;
|
||||
|
||||
template <class F, class U, class = invoke_result_t<F, U>>
|
||||
using get_map_return = optional<fixup_void<invoke_result_t<F, U>>>;
|
||||
// Trait for checking if a type is a tl::optional
|
||||
template <class T> struct is_optional_impl : std::false_type {};
|
||||
template <class T> struct is_optional_impl<optional<T>> : std::true_type {};
|
||||
template <class T> using is_optional = is_optional_impl<decay_t<T>>;
|
||||
|
||||
// Check if invoking F for some Us returns void
|
||||
template <class F, class = void, class... U> struct returns_void_impl;
|
||||
template <class F, class... U>
|
||||
struct returns_void_impl<F, void_t<invoke_result_t<F, U...>>, U...>
|
||||
// Change void to tl::monostate
|
||||
template <class U>
|
||||
using fixup_void = conditional_t<std::is_void<U>::value, monostate, U>;
|
||||
|
||||
template <class F, class U, class = invoke_result_t<F, U>>
|
||||
using get_map_return = optional<fixup_void<invoke_result_t<F, U>>>;
|
||||
|
||||
// Check if invoking F for some Us returns void
|
||||
template <class F, class = void, class... U> struct returns_void_impl;
|
||||
template <class F, class... U>
|
||||
struct returns_void_impl<F, void_t<invoke_result_t<F, U...>>, U...>
|
||||
: std::is_void<invoke_result_t<F, U...>> {};
|
||||
template <class F, class... U>
|
||||
using returns_void = returns_void_impl<F, void, U...>;
|
||||
template <class F, class... U>
|
||||
using returns_void = returns_void_impl<F, void, U...>;
|
||||
|
||||
template <class T, class... U>
|
||||
using enable_if_ret_void = enable_if_t<returns_void<T &&, U...>::value>;
|
||||
template <class T, class... U>
|
||||
using enable_if_ret_void = enable_if_t<returns_void<T &&, U...>::value>;
|
||||
|
||||
template <class T, class... U>
|
||||
using disable_if_ret_void = enable_if_t<!returns_void<T &&, U...>::value>;
|
||||
template <class T, class... U>
|
||||
using disable_if_ret_void = enable_if_t<!returns_void<T &&, U...>::value>;
|
||||
|
||||
template <class T, class U>
|
||||
using enable_forward_value = detail::enable_if_t<
|
||||
std::is_constructible<T, U &&>::value &&
|
||||
template <class T, class U>
|
||||
using enable_forward_value =
|
||||
detail::enable_if_t<std::is_constructible<T, U &&>::value &&
|
||||
!std::is_same<detail::decay_t<U>, in_place_t>::value &&
|
||||
!std::is_same<optional<T>, detail::decay_t<U>>::value>;
|
||||
|
||||
template <class T, class U, class Other>
|
||||
using enable_from_other = detail::enable_if_t<
|
||||
template <class T, class U, class Other>
|
||||
using enable_from_other = detail::enable_if_t<
|
||||
std::is_constructible<T, Other>::value &&
|
||||
!std::is_constructible<T, optional<U> &>::value &&
|
||||
!std::is_constructible<T, optional<U> &&>::value &&
|
||||
@ -188,15 +191,15 @@
|
||||
!std::is_convertible<const optional<U> &, T>::value &&
|
||||
!std::is_convertible<const optional<U> &&, T>::value>;
|
||||
|
||||
template <class T, class U>
|
||||
using enable_assign_forward = detail::enable_if_t<
|
||||
template <class T, class U>
|
||||
using enable_assign_forward = detail::enable_if_t<
|
||||
!std::is_same<optional<T>, detail::decay_t<U>>::value &&
|
||||
!detail::conjunction<std::is_scalar<T>,
|
||||
std::is_same<T, detail::decay_t<U>>>::value &&
|
||||
std::is_constructible<T, U>::value && std::is_assignable<T &, U>::value>;
|
||||
|
||||
template <class T, class U, class Other>
|
||||
using enable_assign_from_other = detail::enable_if_t<
|
||||
template <class T, class U, class Other>
|
||||
using enable_assign_from_other = detail::enable_if_t<
|
||||
std::is_constructible<T, Other>::value &&
|
||||
std::is_assignable<T &, Other>::value &&
|
||||
!std::is_constructible<T, optional<U> &>::value &&
|
||||
@ -213,11 +216,10 @@
|
||||
!std::is_assignable<T &, const optional<U> &&>::value>;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// TODO make a version which works with MSVC
|
||||
template <class T, class U = T> struct is_swappable : std::true_type {};
|
||||
// TODO make a version which works with MSVC
|
||||
template <class T, class U = T> struct is_swappable : std::true_type {};
|
||||
|
||||
template <class T, class U = T>
|
||||
struct is_nothrow_swappable : std::true_type {};
|
||||
template <class T, class U = T> struct is_nothrow_swappable : std::true_type {};
|
||||
#else
|
||||
// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
|
||||
namespace swap_adl_tests {
|
||||
@ -286,11 +288,11 @@ struct is_nothrow_swappable
|
||||
};
|
||||
#endif
|
||||
|
||||
// The storage base manages the actual storage, and correctly propagates
|
||||
// trivial destruction from T This case is for when T is trivially
|
||||
// destructible
|
||||
template <class T, bool = ::std::is_trivially_destructible<T>::value>
|
||||
struct optional_storage_base {
|
||||
// The storage base manages the actual storage, and correctly propagates
|
||||
// trivial destruction from T This case is for when T is trivially
|
||||
// destructible
|
||||
template <class T, bool = ::std::is_trivially_destructible<T>::value>
|
||||
struct optional_storage_base {
|
||||
TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
|
||||
: m_dummy(), m_has_value(false) {}
|
||||
|
||||
@ -312,10 +314,10 @@ struct is_nothrow_swappable
|
||||
};
|
||||
|
||||
bool m_has_value;
|
||||
};
|
||||
};
|
||||
|
||||
// This case is for when T is not trivially destructible
|
||||
template <class T> struct optional_storage_base<T, true> {
|
||||
// This case is for when T is not trivially destructible
|
||||
template <class T> struct optional_storage_base<T, true> {
|
||||
TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
|
||||
: m_dummy(), m_has_value(false) {}
|
||||
|
||||
@ -332,12 +334,11 @@ struct is_nothrow_swappable
|
||||
};
|
||||
|
||||
bool m_has_value = false;
|
||||
};
|
||||
};
|
||||
|
||||
// This base class provides some handy member functions which can be used in
|
||||
// further derived classes
|
||||
template <class T>
|
||||
struct optional_operations_base : optional_storage_base<T> {
|
||||
// This base class provides some handy member functions which can be used in
|
||||
// further derived classes
|
||||
template <class T> struct optional_operations_base : optional_storage_base<T> {
|
||||
using optional_storage_base<T>::optional_storage_base;
|
||||
|
||||
void hard_reset() noexcept {
|
||||
@ -373,18 +374,18 @@ struct is_nothrow_swappable
|
||||
#ifndef TL_OPTIONAL_NO_CONSTRR
|
||||
constexpr const T &&get() const && { return std::move(this->m_value); }
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
// This class manages conditionally having a trivial copy constructor
|
||||
// This specialization is for when T is trivially copy constructible
|
||||
template <class T, bool = IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>
|
||||
struct optional_copy_base : optional_operations_base<T> {
|
||||
// This class manages conditionally having a trivial copy constructor
|
||||
// This specialization is for when T is trivially copy constructible
|
||||
template <class T, bool = IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>
|
||||
struct optional_copy_base : optional_operations_base<T> {
|
||||
using optional_operations_base<T>::optional_operations_base;
|
||||
};
|
||||
};
|
||||
|
||||
// This specialization is for when T is not trivially copy constructible
|
||||
template <class T>
|
||||
struct optional_copy_base<T, false> : optional_operations_base<T> {
|
||||
// This specialization is for when T is not trivially copy constructible
|
||||
template <class T>
|
||||
struct optional_copy_base<T, false> : optional_operations_base<T> {
|
||||
using optional_operations_base<T>::optional_operations_base;
|
||||
|
||||
optional_copy_base() = default;
|
||||
@ -399,7 +400,7 @@ struct is_nothrow_swappable
|
||||
optional_copy_base(optional_copy_base &&rhs) = default;
|
||||
optional_copy_base &operator=(const optional_copy_base &rhs) = default;
|
||||
optional_copy_base &operator=(optional_copy_base &&rhs) = default;
|
||||
};
|
||||
};
|
||||
|
||||
// This class manages conditionally having a trivial move constructor
|
||||
// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
|
||||
@ -407,15 +408,14 @@ struct is_nothrow_swappable
|
||||
// have to make do with a non-trivial move constructor even if T is trivially
|
||||
// move constructible
|
||||
#ifndef TL_OPTIONAL_GCC49
|
||||
template <class T, bool = std::is_trivially_move_constructible<T>::value>
|
||||
struct optional_move_base : optional_copy_base<T> {
|
||||
template <class T, bool = std::is_trivially_move_constructible<T>::value>
|
||||
struct optional_move_base : optional_copy_base<T> {
|
||||
using optional_copy_base<T>::optional_copy_base;
|
||||
};
|
||||
};
|
||||
#else
|
||||
template <class T, bool = false> struct optional_move_base;
|
||||
#endif
|
||||
template <class T>
|
||||
struct optional_move_base<T, false> : optional_copy_base<T> {
|
||||
template <class T> struct optional_move_base<T, false> : optional_copy_base<T> {
|
||||
using optional_copy_base<T>::optional_copy_base;
|
||||
|
||||
optional_move_base() = default;
|
||||
@ -431,18 +431,18 @@ template <class T, bool = false> struct optional_move_base;
|
||||
}
|
||||
optional_move_base &operator=(const optional_move_base &rhs) = default;
|
||||
optional_move_base &operator=(optional_move_base &&rhs) = default;
|
||||
};
|
||||
};
|
||||
|
||||
// This class manages conditionally having a trivial copy assignment operator
|
||||
template <class T, bool = IS_TRIVIALLY_COPY_ASSIGNABLE(T) &&
|
||||
// This class manages conditionally having a trivial copy assignment operator
|
||||
template <class T, bool = IS_TRIVIALLY_COPY_ASSIGNABLE(T) &&
|
||||
IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) &&
|
||||
IS_TRIVIALLY_DESTRUCTIBLE(T)>
|
||||
struct optional_copy_assign_base : optional_move_base<T> {
|
||||
struct optional_copy_assign_base : optional_move_base<T> {
|
||||
using optional_move_base<T>::optional_move_base;
|
||||
};
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct optional_copy_assign_base<T, false> : optional_move_base<T> {
|
||||
template <class T>
|
||||
struct optional_copy_assign_base<T, false> : optional_move_base<T> {
|
||||
using optional_move_base<T>::optional_move_base;
|
||||
|
||||
optional_copy_assign_base() = default;
|
||||
@ -455,7 +455,7 @@ template <class T, bool = false> struct optional_move_base;
|
||||
}
|
||||
optional_copy_assign_base &
|
||||
operator=(optional_copy_assign_base &&rhs) = default;
|
||||
};
|
||||
};
|
||||
|
||||
// This class manages conditionally having a trivial move assignment operator
|
||||
// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
|
||||
@ -463,18 +463,18 @@ template <class T, bool = false> struct optional_move_base;
|
||||
// to make do with a non-trivial move assignment operator even if T is trivially
|
||||
// move assignable
|
||||
#ifndef TL_OPTIONAL_GCC49
|
||||
template <class T, bool = std::is_trivially_destructible<T>::value
|
||||
template <class T, bool = std::is_trivially_destructible<T>::value
|
||||
&&std::is_trivially_move_constructible<T>::value
|
||||
&&std::is_trivially_move_assignable<T>::value>
|
||||
struct optional_move_assign_base : optional_copy_assign_base<T> {
|
||||
struct optional_move_assign_base : optional_copy_assign_base<T> {
|
||||
using optional_copy_assign_base<T>::optional_copy_assign_base;
|
||||
};
|
||||
};
|
||||
#else
|
||||
template <class T, bool = false> struct optional_move_assign_base;
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
struct optional_move_assign_base<T, false> : optional_copy_assign_base<T> {
|
||||
template <class T>
|
||||
struct optional_move_assign_base<T, false> : optional_copy_assign_base<T> {
|
||||
using optional_copy_assign_base<T>::optional_copy_assign_base;
|
||||
|
||||
optional_move_assign_base() = default;
|
||||
@ -490,13 +490,13 @@ template <class T, bool = false> struct optional_move_assign_base;
|
||||
}
|
||||
optional_move_assign_base &
|
||||
operator=(optional_move_assign_base &&rhs) = default;
|
||||
};
|
||||
};
|
||||
|
||||
// optional_delete_ctor_base will conditionally delete copy and move
|
||||
// constructors depending on whether T is copy/move constructible
|
||||
template <class T, bool EnableCopy = std::is_copy_constructible<T>::value,
|
||||
// optional_delete_ctor_base will conditionally delete copy and move
|
||||
// constructors depending on whether T is copy/move constructible
|
||||
template <class T, bool EnableCopy = std::is_copy_constructible<T>::value,
|
||||
bool EnableMove = std::is_move_constructible<T>::value>
|
||||
struct optional_delete_ctor_base {
|
||||
struct optional_delete_ctor_base {
|
||||
optional_delete_ctor_base() = default;
|
||||
optional_delete_ctor_base(const optional_delete_ctor_base &) = default;
|
||||
optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = default;
|
||||
@ -504,9 +504,9 @@ template <class T, bool = false> struct optional_move_assign_base;
|
||||
operator=(const optional_delete_ctor_base &) = default;
|
||||
optional_delete_ctor_base &
|
||||
operator=(optional_delete_ctor_base &&) noexcept = default;
|
||||
};
|
||||
};
|
||||
|
||||
template <class T> struct optional_delete_ctor_base<T, true, false> {
|
||||
template <class T> struct optional_delete_ctor_base<T, true, false> {
|
||||
optional_delete_ctor_base() = default;
|
||||
optional_delete_ctor_base(const optional_delete_ctor_base &) = default;
|
||||
optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = delete;
|
||||
@ -514,9 +514,9 @@ template <class T, bool = false> struct optional_move_assign_base;
|
||||
operator=(const optional_delete_ctor_base &) = default;
|
||||
optional_delete_ctor_base &
|
||||
operator=(optional_delete_ctor_base &&) noexcept = default;
|
||||
};
|
||||
};
|
||||
|
||||
template <class T> struct optional_delete_ctor_base<T, false, true> {
|
||||
template <class T> struct optional_delete_ctor_base<T, false, true> {
|
||||
optional_delete_ctor_base() = default;
|
||||
optional_delete_ctor_base(const optional_delete_ctor_base &) = delete;
|
||||
optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = default;
|
||||
@ -524,9 +524,9 @@ template <class T, bool = false> struct optional_move_assign_base;
|
||||
operator=(const optional_delete_ctor_base &) = default;
|
||||
optional_delete_ctor_base &
|
||||
operator=(optional_delete_ctor_base &&) noexcept = default;
|
||||
};
|
||||
};
|
||||
|
||||
template <class T> struct optional_delete_ctor_base<T, false, false> {
|
||||
template <class T> struct optional_delete_ctor_base<T, false, false> {
|
||||
optional_delete_ctor_base() = default;
|
||||
optional_delete_ctor_base(const optional_delete_ctor_base &) = delete;
|
||||
optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = delete;
|
||||
@ -534,16 +534,16 @@ template <class T, bool = false> struct optional_move_assign_base;
|
||||
operator=(const optional_delete_ctor_base &) = default;
|
||||
optional_delete_ctor_base &
|
||||
operator=(optional_delete_ctor_base &&) noexcept = default;
|
||||
};
|
||||
};
|
||||
|
||||
// optional_delete_assign_base will conditionally delete copy and move
|
||||
// constructors depending on whether T is copy/move constructible + assignable
|
||||
template <class T,
|
||||
// optional_delete_assign_base will conditionally delete copy and move
|
||||
// constructors depending on whether T is copy/move constructible + assignable
|
||||
template <class T,
|
||||
bool EnableCopy = (std::is_copy_constructible<T>::value &&
|
||||
std::is_copy_assignable<T>::value),
|
||||
bool EnableMove = (std::is_move_constructible<T>::value &&
|
||||
std::is_move_assignable<T>::value)>
|
||||
struct optional_delete_assign_base {
|
||||
struct optional_delete_assign_base {
|
||||
optional_delete_assign_base() = default;
|
||||
optional_delete_assign_base(const optional_delete_assign_base &) = default;
|
||||
optional_delete_assign_base(optional_delete_assign_base &&) noexcept =
|
||||
@ -552,9 +552,9 @@ template <class T, bool = false> struct optional_move_assign_base;
|
||||
operator=(const optional_delete_assign_base &) = default;
|
||||
optional_delete_assign_base &
|
||||
operator=(optional_delete_assign_base &&) noexcept = default;
|
||||
};
|
||||
};
|
||||
|
||||
template <class T> struct optional_delete_assign_base<T, true, false> {
|
||||
template <class T> struct optional_delete_assign_base<T, true, false> {
|
||||
optional_delete_assign_base() = default;
|
||||
optional_delete_assign_base(const optional_delete_assign_base &) = default;
|
||||
optional_delete_assign_base(optional_delete_assign_base &&) noexcept =
|
||||
@ -563,9 +563,9 @@ template <class T, bool = false> struct optional_move_assign_base;
|
||||
operator=(const optional_delete_assign_base &) = default;
|
||||
optional_delete_assign_base &
|
||||
operator=(optional_delete_assign_base &&) noexcept = delete;
|
||||
};
|
||||
};
|
||||
|
||||
template <class T> struct optional_delete_assign_base<T, false, true> {
|
||||
template <class T> struct optional_delete_assign_base<T, false, true> {
|
||||
optional_delete_assign_base() = default;
|
||||
optional_delete_assign_base(const optional_delete_assign_base &) = default;
|
||||
optional_delete_assign_base(optional_delete_assign_base &&) noexcept =
|
||||
@ -574,9 +574,9 @@ template <class T, bool = false> struct optional_move_assign_base;
|
||||
operator=(const optional_delete_assign_base &) = delete;
|
||||
optional_delete_assign_base &
|
||||
operator=(optional_delete_assign_base &&) noexcept = default;
|
||||
};
|
||||
};
|
||||
|
||||
template <class T> struct optional_delete_assign_base<T, false, false> {
|
||||
template <class T> struct optional_delete_assign_base<T, false, false> {
|
||||
optional_delete_assign_base() = default;
|
||||
optional_delete_assign_base(const optional_delete_assign_base &) = default;
|
||||
optional_delete_assign_base(optional_delete_assign_base &&) noexcept =
|
||||
@ -585,46 +585,46 @@ template <class T, bool = false> struct optional_move_assign_base;
|
||||
operator=(const optional_delete_assign_base &) = delete;
|
||||
optional_delete_assign_base &
|
||||
operator=(optional_delete_assign_base &&) noexcept = delete;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
|
||||
/// \brief A tag type to represent an empty optional
|
||||
struct nullopt_t {
|
||||
/// \brief A tag type to represent an empty optional
|
||||
struct nullopt_t {
|
||||
struct do_not_use {};
|
||||
constexpr explicit nullopt_t(do_not_use, do_not_use) noexcept {}
|
||||
};
|
||||
/// \brief Represents an empty optional
|
||||
/// \synopsis static constexpr nullopt_t nullopt;
|
||||
///
|
||||
/// *Examples*:
|
||||
/// ```
|
||||
/// tl::optional<int> a = tl::nullopt;
|
||||
/// void foo (tl::optional<int>);
|
||||
/// foo(tl::nullopt); //pass an empty optional
|
||||
/// ```
|
||||
static constexpr nullopt_t nullopt{nullopt_t::do_not_use{},
|
||||
};
|
||||
/// \brief Represents an empty optional
|
||||
/// \synopsis static constexpr nullopt_t nullopt;
|
||||
///
|
||||
/// *Examples*:
|
||||
/// ```
|
||||
/// tl::optional<int> a = tl::nullopt;
|
||||
/// void foo (tl::optional<int>);
|
||||
/// foo(tl::nullopt); //pass an empty optional
|
||||
/// ```
|
||||
static constexpr nullopt_t nullopt{nullopt_t::do_not_use{},
|
||||
nullopt_t::do_not_use{}};
|
||||
|
||||
class bad_optional_access : public std::exception {
|
||||
public:
|
||||
class bad_optional_access : public std::exception {
|
||||
public:
|
||||
bad_optional_access() = default;
|
||||
const char *what() const noexcept { return "Optional has no value"; }
|
||||
};
|
||||
};
|
||||
|
||||
/// An optional object is an object that contains the storage for another
|
||||
/// object and manages the lifetime of this contained object, if any. The
|
||||
/// contained object may be initialized after the optional object has been
|
||||
/// initialized, and may be destroyed before the optional object has been
|
||||
/// destroyed. The initialization state of the contained object is tracked by
|
||||
/// the optional object.
|
||||
template <class T>
|
||||
class optional : private detail::optional_move_assign_base<T>,
|
||||
/// An optional object is an object that contains the storage for another
|
||||
/// object and manages the lifetime of this contained object, if any. The
|
||||
/// contained object may be initialized after the optional object has been
|
||||
/// initialized, and may be destroyed before the optional object has been
|
||||
/// destroyed. The initialization state of the contained object is tracked by
|
||||
/// the optional object.
|
||||
template <class T>
|
||||
class optional : private detail::optional_move_assign_base<T>,
|
||||
private detail::optional_delete_ctor_base<T>,
|
||||
private detail::optional_delete_assign_base<T> {
|
||||
using base = detail::optional_move_assign_base<T>;
|
||||
|
||||
public:
|
||||
public:
|
||||
// The different versions for C++14 and 11 are needed because deduced return
|
||||
// types are not SFINAE-safe. This provides better support for things like
|
||||
// generic lambdas. C.f.
|
||||
@ -1085,8 +1085,7 @@ template <class T, bool = false> struct optional_move_assign_base;
|
||||
/// optional(in_place_t, Args&&... args);
|
||||
template <class... Args>
|
||||
constexpr explicit optional(
|
||||
detail::enable_if_t<std::is_constructible<T, Args...>::value,
|
||||
in_place_t>,
|
||||
detail::enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>,
|
||||
Args &&... args)
|
||||
: base(in_place, std::forward<Args>(args)...) {}
|
||||
|
||||
@ -1119,9 +1118,9 @@ template <class T, bool = false> struct optional_move_assign_base;
|
||||
|
||||
/// Converting copy constructor.
|
||||
/// \synopsis template <class U> optional(const optional<U> &rhs);
|
||||
template <class U, detail::enable_from_other<T, U, const U &> * = nullptr,
|
||||
detail::enable_if_t<std::is_convertible<const U &, T>::value> * =
|
||||
nullptr>
|
||||
template <
|
||||
class U, detail::enable_from_other<T, U, const U &> * = nullptr,
|
||||
detail::enable_if_t<std::is_convertible<const U &, T>::value> * = nullptr>
|
||||
optional(const optional<U> &rhs) {
|
||||
this->construct(*rhs);
|
||||
}
|
||||
@ -1314,9 +1313,7 @@ template <class T, bool = false> struct optional_move_assign_base;
|
||||
|
||||
#ifndef TL_OPTIONAL_NO_CONSTRR
|
||||
/// \exclude
|
||||
constexpr const T &&operator*() const && {
|
||||
return std::move(this->m_value);
|
||||
}
|
||||
constexpr const T &&operator*() const && { return std::move(this->m_value); }
|
||||
#endif
|
||||
|
||||
/// \returns whether or not the optional has a value
|
||||
@ -1384,234 +1381,233 @@ template <class T, bool = false> struct optional_move_assign_base;
|
||||
this->m_has_value = false;
|
||||
}
|
||||
}
|
||||
}; // namespace tl
|
||||
}; // namespace tl
|
||||
|
||||
/// \group relop
|
||||
/// \brief Compares two optional objects
|
||||
/// \details If both optionals contain a value, they are compared with `T`s
|
||||
/// relational operators. Otherwise `lhs` and `rhs` are equal only if they are
|
||||
/// both empty, and `lhs` is less than `rhs` only if `rhs` is empty and `lhs`
|
||||
/// is not.
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator==(const optional<T> &lhs,
|
||||
/// \group relop
|
||||
/// \brief Compares two optional objects
|
||||
/// \details If both optionals contain a value, they are compared with `T`s
|
||||
/// relational operators. Otherwise `lhs` and `rhs` are equal only if they are
|
||||
/// both empty, and `lhs` is less than `rhs` only if `rhs` is empty and `lhs`
|
||||
/// is not.
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator==(const optional<T> &lhs,
|
||||
const optional<U> &rhs) {
|
||||
return lhs.has_value() == rhs.has_value() &&
|
||||
(!lhs.has_value() || *lhs == *rhs);
|
||||
}
|
||||
/// \group relop
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator!=(const optional<T> &lhs,
|
||||
}
|
||||
/// \group relop
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator!=(const optional<T> &lhs,
|
||||
const optional<U> &rhs) {
|
||||
return lhs.has_value() != rhs.has_value() ||
|
||||
(lhs.has_value() && *lhs != *rhs);
|
||||
}
|
||||
/// \group relop
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator<(const optional<T> &lhs,
|
||||
}
|
||||
/// \group relop
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator<(const optional<T> &lhs,
|
||||
const optional<U> &rhs) {
|
||||
return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs);
|
||||
}
|
||||
/// \group relop
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator>(const optional<T> &lhs,
|
||||
}
|
||||
/// \group relop
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator>(const optional<T> &lhs,
|
||||
const optional<U> &rhs) {
|
||||
return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs);
|
||||
}
|
||||
/// \group relop
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator<=(const optional<T> &lhs,
|
||||
}
|
||||
/// \group relop
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator<=(const optional<T> &lhs,
|
||||
const optional<U> &rhs) {
|
||||
return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs);
|
||||
}
|
||||
/// \group relop
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator>=(const optional<T> &lhs,
|
||||
}
|
||||
/// \group relop
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator>=(const optional<T> &lhs,
|
||||
const optional<U> &rhs) {
|
||||
return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs);
|
||||
}
|
||||
}
|
||||
|
||||
/// \group relop_nullopt
|
||||
/// \brief Compares an optional to a `nullopt`
|
||||
/// \details Equivalent to comparing the optional to an empty optional
|
||||
template <class T>
|
||||
inline constexpr bool operator==(const optional<T> &lhs, nullopt_t) noexcept {
|
||||
/// \group relop_nullopt
|
||||
/// \brief Compares an optional to a `nullopt`
|
||||
/// \details Equivalent to comparing the optional to an empty optional
|
||||
template <class T>
|
||||
inline constexpr bool operator==(const optional<T> &lhs, nullopt_t) noexcept {
|
||||
return !lhs.has_value();
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator==(nullopt_t, const optional<T> &rhs) noexcept {
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator==(nullopt_t, const optional<T> &rhs) noexcept {
|
||||
return !rhs.has_value();
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator!=(const optional<T> &lhs, nullopt_t) noexcept {
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator!=(const optional<T> &lhs, nullopt_t) noexcept {
|
||||
return lhs.has_value();
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator!=(nullopt_t, const optional<T> &rhs) noexcept {
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator!=(nullopt_t, const optional<T> &rhs) noexcept {
|
||||
return rhs.has_value();
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator<(const optional<T> &, nullopt_t) noexcept {
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator<(const optional<T> &, nullopt_t) noexcept {
|
||||
return false;
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator<(nullopt_t, const optional<T> &rhs) noexcept {
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator<(nullopt_t, const optional<T> &rhs) noexcept {
|
||||
return rhs.has_value();
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator<=(const optional<T> &lhs, nullopt_t) noexcept {
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator<=(const optional<T> &lhs, nullopt_t) noexcept {
|
||||
return !lhs.has_value();
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator<=(nullopt_t, const optional<T> &) noexcept {
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator<=(nullopt_t, const optional<T> &) noexcept {
|
||||
return true;
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator>(const optional<T> &lhs, nullopt_t) noexcept {
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator>(const optional<T> &lhs, nullopt_t) noexcept {
|
||||
return lhs.has_value();
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator>(nullopt_t, const optional<T> &) noexcept {
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator>(nullopt_t, const optional<T> &) noexcept {
|
||||
return false;
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator>=(const optional<T> &, nullopt_t) noexcept {
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator>=(const optional<T> &, nullopt_t) noexcept {
|
||||
return true;
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator>=(nullopt_t, const optional<T> &rhs) noexcept {
|
||||
}
|
||||
/// \group relop_nullopt
|
||||
template <class T>
|
||||
inline constexpr bool operator>=(nullopt_t, const optional<T> &rhs) noexcept {
|
||||
return !rhs.has_value();
|
||||
}
|
||||
}
|
||||
|
||||
/// \group relop_t
|
||||
/// \brief Compares the optional with a value.
|
||||
/// \details If the optional has a value, it is compared with the other value
|
||||
/// using `T`s relational operators. Otherwise, the optional is considered
|
||||
/// less than the value.
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator==(const optional<T> &lhs, const U &rhs) {
|
||||
/// \group relop_t
|
||||
/// \brief Compares the optional with a value.
|
||||
/// \details If the optional has a value, it is compared with the other value
|
||||
/// using `T`s relational operators. Otherwise, the optional is considered
|
||||
/// less than the value.
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator==(const optional<T> &lhs, const U &rhs) {
|
||||
return lhs.has_value() ? *lhs == rhs : false;
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator==(const U &lhs, const optional<T> &rhs) {
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator==(const U &lhs, const optional<T> &rhs) {
|
||||
return rhs.has_value() ? lhs == *rhs : false;
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator!=(const optional<T> &lhs, const U &rhs) {
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator!=(const optional<T> &lhs, const U &rhs) {
|
||||
return lhs.has_value() ? *lhs != rhs : true;
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator!=(const U &lhs, const optional<T> &rhs) {
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator!=(const U &lhs, const optional<T> &rhs) {
|
||||
return rhs.has_value() ? lhs != *rhs : true;
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator<(const optional<T> &lhs, const U &rhs) {
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator<(const optional<T> &lhs, const U &rhs) {
|
||||
return lhs.has_value() ? *lhs < rhs : true;
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator<(const U &lhs, const optional<T> &rhs) {
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator<(const U &lhs, const optional<T> &rhs) {
|
||||
return rhs.has_value() ? lhs < *rhs : false;
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator<=(const optional<T> &lhs, const U &rhs) {
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator<=(const optional<T> &lhs, const U &rhs) {
|
||||
return lhs.has_value() ? *lhs <= rhs : true;
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator<=(const U &lhs, const optional<T> &rhs) {
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator<=(const U &lhs, const optional<T> &rhs) {
|
||||
return rhs.has_value() ? lhs <= *rhs : false;
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator>(const optional<T> &lhs, const U &rhs) {
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator>(const optional<T> &lhs, const U &rhs) {
|
||||
return lhs.has_value() ? *lhs > rhs : false;
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator>(const U &lhs, const optional<T> &rhs) {
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator>(const U &lhs, const optional<T> &rhs) {
|
||||
return rhs.has_value() ? lhs > *rhs : true;
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator>=(const optional<T> &lhs, const U &rhs) {
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator>=(const optional<T> &lhs, const U &rhs) {
|
||||
return lhs.has_value() ? *lhs >= rhs : false;
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator>=(const U &lhs, const optional<T> &rhs) {
|
||||
}
|
||||
/// \group relop_t
|
||||
template <class T, class U>
|
||||
inline constexpr bool operator>=(const U &lhs, const optional<T> &rhs) {
|
||||
return rhs.has_value() ? lhs >= *rhs : true;
|
||||
}
|
||||
}
|
||||
|
||||
/// \synopsis template <class T>\nvoid swap(optional<T> &lhs, optional<T>
|
||||
/// &rhs);
|
||||
template <class T,
|
||||
detail::enable_if_t<std::is_move_constructible<T>::value> * =
|
||||
nullptr,
|
||||
/// \synopsis template <class T>\nvoid swap(optional<T> &lhs, optional<T>
|
||||
/// &rhs);
|
||||
template <class T,
|
||||
detail::enable_if_t<std::is_move_constructible<T>::value> * = nullptr,
|
||||
detail::enable_if_t<detail::is_swappable<T>::value> * = nullptr>
|
||||
void swap(optional<T> & lhs,
|
||||
optional<T> & rhs) noexcept(noexcept(lhs.swap(rhs))) {
|
||||
void swap(optional<T> &lhs,
|
||||
optional<T> &rhs) noexcept(noexcept(lhs.swap(rhs))) {
|
||||
return lhs.swap(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline constexpr optional<detail::decay_t<T>> make_optional(T && v) {
|
||||
template <class T>
|
||||
inline constexpr optional<detail::decay_t<T>> make_optional(T &&v) {
|
||||
return optional<detail::decay_t<T>>(std::forward<T>(v));
|
||||
}
|
||||
template <class T, class... Args>
|
||||
inline constexpr optional<T> make_optional(Args && ... args) {
|
||||
}
|
||||
template <class T, class... Args>
|
||||
inline constexpr optional<T> make_optional(Args &&... args) {
|
||||
return optional<T>(in_place, std::forward<Args>(args)...);
|
||||
}
|
||||
template <class T, class U, class... Args>
|
||||
inline constexpr optional<T> make_optional(std::initializer_list<U> il,
|
||||
Args && ... args) {
|
||||
}
|
||||
template <class T, class U, class... Args>
|
||||
inline constexpr optional<T> make_optional(std::initializer_list<U> il,
|
||||
Args &&... args) {
|
||||
return optional<T>(in_place, il, std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
template <class T> optional(T)->optional<T>;
|
||||
template <class T> optional(T)->optional<T>;
|
||||
#endif
|
||||
|
||||
/// \exclude
|
||||
namespace detail {
|
||||
/// \exclude
|
||||
namespace detail {
|
||||
#ifdef TL_OPTIONAL_CX14
|
||||
template <class Opt, class F,
|
||||
template <class Opt, class F,
|
||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||
*std::declval<Opt>())),
|
||||
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
|
||||
constexpr auto map_impl(Opt &&opt, F &&f) {
|
||||
constexpr auto map_impl(Opt &&opt, F &&f) {
|
||||
return opt.has_value()
|
||||
? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))
|
||||
: optional<Ret>(nullopt);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Opt, class F,
|
||||
template <class Opt, class F,
|
||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||
*std::declval<Opt>())),
|
||||
detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
|
||||
auto map_impl(Opt &&opt, F &&f) {
|
||||
auto map_impl(Opt &&opt, F &&f) {
|
||||
if (opt.has_value()) {
|
||||
detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
|
||||
return monostate{};
|
||||
}
|
||||
|
||||
return optional<Ret>(nullopt);
|
||||
}
|
||||
}
|
||||
#else
|
||||
template <class Opt, class F,
|
||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||
@ -1638,7 +1634,7 @@ auto map_impl(Opt &&opt, F &&f) -> optional<monostate> {
|
||||
return nullopt;
|
||||
}
|
||||
#endif
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
|
||||
} // namespace tl
|
||||
|
||||
@ -1654,4 +1650,5 @@ template <class T> struct hash<tl::optional<T>> {
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
#define TL_OPTIONAL_EXPECTED_MUTEX
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user