[*] Further reduced std references

This commit is contained in:
Reece Wilson 2024-03-11 18:05:34 +00:00
parent d717f60508
commit 5ebb8b0fa8
2 changed files with 305 additions and 113 deletions

View File

@ -57,7 +57,7 @@
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign<T>::value #define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign<T>::value
// This one will be different for GCC 5.7 if it's ever supported // This one will be different for GCC 5.7 if it's ever supported
#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value #define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) AuIsTriviallyDestructible<T>::value
// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks std::vector // GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks std::vector
// for non-copyable types // for non-copyable types
@ -84,13 +84,13 @@ namespace tl {
tl::detail::is_trivially_copy_constructible<T>::value tl::detail::is_trivially_copy_constructible<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ #define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
std::is_trivially_copy_assignable<T>::value std::is_trivially_copy_assignable<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value #define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) AuIsTriviallyDestructible<T>::value
#else #else
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ #define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
std::is_trivially_copy_constructible<T>::value AuIsTriviallyCopyConstructible<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ #define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
std::is_trivially_copy_assignable<T>::value AuIsTriviallyCopyAssignable<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value #define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) AuIsTriviallyDestructible<T>::value
#endif #endif
#if __cplusplus > 201103L #if __cplusplus > 201103L
@ -127,10 +127,10 @@ namespace tl {
#ifndef TL_TRAITS_MUTEX #ifndef TL_TRAITS_MUTEX
#define TL_TRAITS_MUTEX #define TL_TRAITS_MUTEX
// C++14-style aliases for brevity // C++14-style aliases for brevity
template <class T> using remove_const_t = typename std::remove_const<T>::type; template <class T> using remove_const_t = typename AuRemoveConst<T>::type;
template <class T> template <class T>
using remove_reference_t = typename std::remove_reference<T>::type; using remove_reference_t = typename AuRemoveReference<T>::type;
template <class T> using decay_t = typename std::decay<T>::type; template <class T> using decay_t = typename AuDecay<T>::type;
template <bool E, class T = void> template <bool E, class T = void>
using enable_if_t = typename AuEnableIf<E, T>::type; using enable_if_t = typename AuEnableIf<E, T>::type;
template <bool B, class T, class F> template <bool B, class T, class F>
@ -241,7 +241,7 @@ namespace tl {
{ }; { };
template <class T> tag swap(T &, T &); template <class T> tag swap(T &, T &);
template <class T, std::size_t N> tag swap(T(&a)[N], T(&b)[N]); template <class T, AuUInt N> tag swap(T(&a)[N], T(&b)[N]);
// helper functions to test if an unqualified swap is possible, and if it // helper functions to test if an unqualified swap is possible, and if it
// becomes std::swap // becomes std::swap
@ -253,40 +253,38 @@ namespace tl {
template <class, class> AuFalseType uses_std(...); template <class, class> AuFalseType uses_std(...);
template <class T, class U> template <class T, class U>
std::is_same<decltype(swap(AuDecalVal<T &>(), AuDecalVal<U &>())), tag> AuIsSame<decltype(swap(AuDecalVal<T &>(), AuDecalVal<U &>())), tag>
uses_std(int); uses_std(int);
template <class T> template <class T>
struct is_std_swap_noexcept struct is_std_swap_noexcept
: std::integral_constant<bool, : AuBoolType<
std::is_nothrow_move_constructible<T>::value && AuIsNothrowMoveConstructible<T>::value &&
std::is_nothrow_move_assignable<T>::value> AuIsNothrowMoveAssignable<T>::value>
{ }; { };
template <class T, std::size_t N> template <class T, AuUInt N>
struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T>
{ }; { };
template <class T, class U> template <class T, class U>
struct is_adl_swap_noexcept struct is_adl_swap_noexcept
: std::integral_constant<bool, noexcept(can_swap<T, U>(0))> : AuBoolType<noexcept(can_swap<T, U>(0))>
{ }; { };
} // namespace swap_adl_tests } // namespace swap_adl_tests
template <class T, class U = T> template <class T, class U = T>
struct is_swappable struct is_swappable
: std::integral_constant< : AuBoolType<
bool,
decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value && decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
(!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value || (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
(std::is_move_assignable<T>::value && (AuIsMoveAssignable<T>::value &&
std::is_move_constructible<T>::value))> AuIsMoveConstructible<T>::value))>
{ }; { };
template <class T, std::size_t N> template <class T, AuUInt N>
struct is_swappable<T[N], T[N]> struct is_swappable<T[N], T[N]>
: std::integral_constant< : AuBoolType<
bool,
decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value && decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
(!decltype( (!decltype(
detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value || detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value ||
@ -295,8 +293,7 @@ namespace tl {
template <class T, class U = T> template <class T, class U = T>
struct is_nothrow_swappable struct is_nothrow_swappable
: std::integral_constant< : AuBoolType<
bool,
is_swappable<T, U>::value && is_swappable<T, U>::value &&
((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value
&&detail::swap_adl_tests::is_std_swap_noexcept<T>::value) || &&detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||
@ -323,7 +320,7 @@ namespace tl {
// Change void to tl::monostate // Change void to tl::monostate
template <class U> template <class U>
using fixup_void = conditional_t<std::is_void<U>::value, monostate, U>; using fixup_void = conditional_t<AuIsVoid<U>::value, monostate, U>;
template <class F, class U, class = invoke_result_t<F, U>> template <class F, class U, class = invoke_result_t<F, U>>
using get_map_return = optional<fixup_void<invoke_result_t<F, U>>>; using get_map_return = optional<fixup_void<invoke_result_t<F, U>>>;
@ -332,7 +329,7 @@ namespace tl {
template <class F, class = void, class... U> struct returns_void_impl; template <class F, class = void, class... U> struct returns_void_impl;
template <class F, class... U> template <class F, class... U>
struct returns_void_impl<F, void_t<invoke_result_t<F, U...>>, U...> struct returns_void_impl<F, void_t<invoke_result_t<F, U...>>, U...>
: std::is_void<invoke_result_t<F, U...>> : AuIsVoid<invoke_result_t<F, U...>>
{ }; { };
template <class F, class... U> template <class F, class... U>
using returns_void = AuIsVoid<AuResultOf_t<F, U...>>; // returns_void_impl<F, void, U...>; using returns_void = AuIsVoid<AuResultOf_t<F, U...>>; // returns_void_impl<F, void, U...>;
@ -345,50 +342,50 @@ namespace tl {
template <class T, class U> template <class T, class U>
using enable_forward_value = using enable_forward_value =
detail::enable_if_t<std::is_constructible<T, U &&>::value && detail::enable_if_t<AuIsConstructible<T, U &&>::value &&
!std::is_same<detail::decay_t<U>, in_place_t>::value && !AuIsSame<detail::decay_t<U>, in_place_t>::value &&
!std::is_same<optional<T>, detail::decay_t<U>>::value>; !AuIsSame<optional<T>, detail::decay_t<U>>::value>;
template <class T, class U, class Other> template <class T, class U, class Other>
using enable_from_other = detail::enable_if_t< using enable_from_other = detail::enable_if_t<
std::is_constructible<T, Other>::value && AuIsConstructible<T, Other>::value &&
!std::is_constructible<T, optional<U> &>::value && !AuIsConstructible<T, optional<U> &>::value &&
!std::is_constructible<T, optional<U> &&>::value && !AuIsConstructible<T, optional<U> &&>::value &&
!std::is_constructible<T, const optional<U> &>::value && !AuIsConstructible<T, const optional<U> &>::value &&
!std::is_constructible<T, const optional<U> &&>::value && !AuIsConstructible<T, const optional<U> &&>::value &&
!std::is_convertible<optional<U> &, T>::value && !AuIsConvertible<optional<U> &, T>::value &&
!std::is_convertible<optional<U> &&, T>::value && !AuIsConvertible<optional<U> &&, T>::value &&
!std::is_convertible<const optional<U> &, T>::value && !AuIsConvertible<const optional<U> &, T>::value &&
!std::is_convertible<const optional<U> &&, T>::value>; !AuIsConvertible<const optional<U> &&, T>::value>;
template <class T, class U> template <class T, class U>
using enable_assign_forward = detail::enable_if_t< using enable_assign_forward = detail::enable_if_t<
!std::is_same<optional<T>, detail::decay_t<U>>::value && !AuIsSame<optional<T>, detail::decay_t<U>>::value &&
!detail::conjunction<std::is_scalar<T>, !detail::conjunction<std::is_scalar<T>,
std::is_same<T, detail::decay_t<U>>>::value && AuIsSame<T, detail::decay_t<U>>>::value &&
std::is_constructible<T, U>::value &&std::is_assignable<T &, U>::value>; AuIsConstructible<T, U>::value &&AuIsAssignable<T &, U>::value>;
template <class T, class U, class Other> template <class T, class U, class Other>
using enable_assign_from_other = detail::enable_if_t< using enable_assign_from_other = detail::enable_if_t<
std::is_constructible<T, Other>::value && AuIsConstructible<T, Other>::value &&
std::is_assignable<T &, Other>::value && AuIsAssignable<T &, Other>::value &&
!std::is_constructible<T, optional<U> &>::value && !AuIsConstructible<T, optional<U> &>::value &&
!std::is_constructible<T, optional<U> &&>::value && !AuIsConstructible<T, optional<U> &&>::value &&
!std::is_constructible<T, const optional<U> &>::value && !AuIsConstructible<T, const optional<U> &>::value &&
!std::is_constructible<T, const optional<U> &&>::value && !AuIsConstructible<T, const optional<U> &&>::value &&
!std::is_convertible<optional<U> &, T>::value && !AuIsConvertible<optional<U> &, T>::value &&
!std::is_convertible<optional<U> &&, T>::value && !AuIsConvertible<optional<U> &&, T>::value &&
!std::is_convertible<const optional<U> &, T>::value && !AuIsConvertible<const optional<U> &, T>::value &&
!std::is_convertible<const optional<U> &&, T>::value && !AuIsConvertible<const optional<U> &&, T>::value &&
!std::is_assignable<T &, optional<U> &>::value && !AuIsAssignable<T &, optional<U> &>::value &&
!std::is_assignable<T &, optional<U> &&>::value && !AuIsAssignable<T &, optional<U> &&>::value &&
!std::is_assignable<T &, const optional<U> &>::value && !AuIsAssignable<T &, const optional<U> &>::value &&
!std::is_assignable<T &, const optional<U> &&>::value>; !AuIsAssignable<T &, const optional<U> &&>::value>;
// The storage base manages the actual storage, and correctly propagates // The storage base manages the actual storage, and correctly propagates
// trivial destruction from T. This case is for when T is not trivially // trivial destruction from T. This case is for when T is not trivially
// destructible. // destructible.
template <class T, bool = ::std::is_trivially_destructible<T>::value> template <class T, bool = AuIsTriviallyDestructible<T>::value>
struct optional_storage_base struct optional_storage_base
{ {
TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
@ -548,7 +545,7 @@ namespace tl {
// have to make do with a non-trivial move constructor even if T is trivially // have to make do with a non-trivial move constructor even if T is trivially
// move constructible // move constructible
#ifndef TL_OPTIONAL_GCC49 #ifndef TL_OPTIONAL_GCC49
template <class T, bool = std::is_trivially_move_constructible<T>::value> template <class T, bool = AuIsTriviallyMoveConstructible<T>::value>
struct optional_move_base : optional_copy_base<T> struct optional_move_base : optional_copy_base<T>
{ {
using optional_copy_base<T>::optional_copy_base; using optional_copy_base<T>::optional_copy_base;
@ -564,7 +561,7 @@ namespace tl {
optional_move_base(const optional_move_base &rhs) = default; optional_move_base(const optional_move_base &rhs) = default;
optional_move_base(optional_move_base &&rhs) noexcept( optional_move_base(optional_move_base &&rhs) noexcept(
std::is_nothrow_move_constructible<T>::value) AuIsNothrowMoveConstructible<T>::value)
{ {
if (rhs.has_value()) if (rhs.has_value())
{ {
@ -608,13 +605,13 @@ namespace tl {
// This class manages conditionally having a trivial move assignment operator // This class manages conditionally having a trivial move assignment operator
// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it // Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
// doesn't implement an analogue to std::is_trivially_move_assignable. We have // doesn't implement an analogue to AuIsTriviallyAssignable. We have
// to make do with a non-trivial move assignment operator even if T is trivially // to make do with a non-trivial move assignment operator even if T is trivially
// move assignable // move assignable
#ifndef TL_OPTIONAL_GCC49 #ifndef TL_OPTIONAL_GCC49
template <class T, bool = std::is_trivially_destructible<T>::value template <class T, bool = AuIsTriviallyDestructible<T>::value
&&std::is_trivially_move_constructible<T>::value &&AuIsTriviallyMoveConstructible<T>::value
&&std::is_trivially_move_assignable<T>::value> &&AuIsTriviallyMoveAssignable<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; using optional_copy_assign_base<T>::optional_copy_assign_base;
@ -638,8 +635,8 @@ namespace tl {
optional_move_assign_base & optional_move_assign_base &
operator=(optional_move_assign_base &&rhs) noexcept( operator=(optional_move_assign_base &&rhs) noexcept(
std::is_nothrow_move_constructible<T>::value AuIsNothrowMoveConstructible<T>::value
&&std::is_nothrow_move_assignable<T>::value) &&AuIsNothrowMoveAssignable<T>::value)
{ {
this->assign(AuMove(rhs)); this->assign(AuMove(rhs));
return *this; return *this;
@ -648,8 +645,8 @@ namespace tl {
// optional_delete_ctor_base will conditionally delete copy and move // optional_delete_ctor_base will conditionally delete copy and move
// constructors depending on whether T is copy/move constructible // constructors depending on whether T is copy/move constructible
template <class T, bool EnableCopy = std::is_copy_constructible<T>::value, template <class T, bool EnableCopy = AuIsCopyConstructible<T>::value,
bool EnableMove = std::is_move_constructible<T>::value> bool EnableMove = AuIsMoveConstructible<T>::value>
struct optional_delete_ctor_base struct optional_delete_ctor_base
{ {
optional_delete_ctor_base() = default; optional_delete_ctor_base() = default;
@ -697,10 +694,10 @@ namespace tl {
// optional_delete_assign_base will conditionally delete copy and move // optional_delete_assign_base will conditionally delete copy and move
// constructors depending on whether T is copy/move constructible + assignable // constructors depending on whether T is copy/move constructible + assignable
template <class T, template <class T,
bool EnableCopy = (std::is_copy_constructible<T>::value && bool EnableCopy = (AuIsCopyConstructible<T>::value &&
std::is_copy_assignable<T>::value), AuIsCopyAssignable<T>::value),
bool EnableMove = (std::is_move_constructible<T>::value && bool EnableMove = (AuIsMoveConstructible<T>::value &&
std::is_move_assignable<T>::value)> AuIsMoveAssignable<T>::value)>
struct optional_delete_assign_base struct optional_delete_assign_base
{ {
optional_delete_assign_base() = default; optional_delete_assign_base() = default;
@ -786,9 +783,9 @@ namespace tl {
{ {
using base = detail::optional_move_assign_base<T>; using base = detail::optional_move_assign_base<T>;
static_assert(!std::is_same<T, in_place_t>::value, static_assert(!AuIsSame<T, in_place_t>::value,
"instantiation of optional with in_place_t is ill-formed"); "instantiation of optional with in_place_t is ill-formed");
static_assert(!std::is_same<detail::decay_t<T>, nullopt_t>::value, static_assert(!AuIsSame<detail::decay_t<T>, nullopt_t>::value,
"instantiation of optional with nullopt_t is ill-formed"); "instantiation of optional with nullopt_t is ill-formed");
public: public:
@ -1457,14 +1454,14 @@ namespace tl {
/// Returns `u` if `*this` has a value, otherwise an empty optional. /// Returns `u` if `*this` has a value, otherwise an empty optional.
template <class U> template <class U>
constexpr optional<typename std::decay<U>::type> conjunction(U &&u) const constexpr optional<typename AuDecay<U>::type> conjunction(U &&u) const
{ {
using result = optional<detail::decay_t<U>>; using result = optional<detail::decay_t<U>>;
return has_value() ? result{u} : result { nullopt }; return has_value() ? result{u} : result { nullopt };
} }
template <class U> template <class U>
constexpr optional<typename std::decay<U>::type> Conjunction(U &&u) const constexpr optional<typename AuDecay<U>::type> Conjunction(U &&u) const
{ {
using result = optional<detail::decay_t<U>>; using result = optional<detail::decay_t<U>>;
return has_value() ? result{u} : result { nullopt }; return has_value() ? result{u} : result { nullopt };
@ -1599,14 +1596,14 @@ namespace tl {
/// Constructs the stored value in-place using the given arguments. /// Constructs the stored value in-place using the given arguments.
template <class... Args> template <class... Args>
constexpr explicit optional( constexpr explicit optional(
detail::enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>, detail::enable_if_t<AuIsConstructible<T, Args...>::value, in_place_t>,
Args &&... args) Args &&... args)
: base(in_place, AuForward<Args>(args)...) : base(in_place, AuForward<Args>(args)...)
{ } { }
template <class U, class... Args> template <class U, class... Args>
TL_OPTIONAL_11_CONSTEXPR explicit optional( TL_OPTIONAL_11_CONSTEXPR explicit optional(
detail::enable_if_t<std::is_constructible<T, std::initializer_list<U> &, detail::enable_if_t<AuIsConstructible<T, std::initializer_list<U> &,
Args &&...>::value, Args &&...>::value,
in_place_t>, in_place_t>,
std::initializer_list<U> il, Args &&... args) std::initializer_list<U> il, Args &&... args)
@ -1617,14 +1614,14 @@ namespace tl {
/// Constructs the stored value with `u`. /// Constructs the stored value with `u`.
template < template <
class U = T, class U = T,
detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr, detail::enable_if_t<AuIsConvertible<U &&, T>::value> * = nullptr,
detail::enable_forward_value<T, U> * = nullptr> detail::enable_forward_value<T, U> * = nullptr>
constexpr optional(U &&u) : base(in_place, AuForward<U>(u)) constexpr optional(U &&u) : base(in_place, AuForward<U>(u))
{ } { }
template < template <
class U = T, class U = T,
detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr, detail::enable_if_t<!AuIsConvertible<U &&, T>::value> * = nullptr,
detail::enable_forward_value<T, U> * = nullptr> detail::enable_forward_value<T, U> * = nullptr>
constexpr explicit optional(U &&u) : base(in_place, AuForward<U>(u)) constexpr explicit optional(U &&u) : base(in_place, AuForward<U>(u))
{ } { }
@ -1632,7 +1629,7 @@ namespace tl {
/// Converting copy constructor. /// Converting copy constructor.
template < template <
class U, detail::enable_from_other<T, U, const U &> * = nullptr, class U, detail::enable_from_other<T, U, const U &> * = nullptr,
detail::enable_if_t<std::is_convertible<const U &, T>::value> * = nullptr> detail::enable_if_t<AuIsConvertible<const U &, T>::value> * = nullptr>
optional(const optional<U> &rhs) optional(const optional<U> &rhs)
{ {
if (rhs.has_value()) if (rhs.has_value())
@ -1642,7 +1639,7 @@ namespace tl {
} }
template <class U, detail::enable_from_other<T, U, const U &> * = nullptr, template <class U, detail::enable_from_other<T, U, const U &> * = nullptr,
detail::enable_if_t<!std::is_convertible<const U &, T>::value> * = detail::enable_if_t<!AuIsConvertible<const U &, T>::value> * =
nullptr> nullptr>
explicit optional(const optional<U> &rhs) explicit optional(const optional<U> &rhs)
{ {
@ -1655,7 +1652,7 @@ namespace tl {
/// Converting move constructor. /// Converting move constructor.
template < template <
class U, detail::enable_from_other<T, U, U &&> * = nullptr, class U, detail::enable_from_other<T, U, U &&> * = nullptr,
detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr> detail::enable_if_t<AuIsConvertible<U &&, T>::value> * = nullptr>
optional(optional<U> &&rhs) optional(optional<U> &&rhs)
{ {
if (rhs.has_value()) if (rhs.has_value())
@ -1666,7 +1663,7 @@ namespace tl {
template < template <
class U, detail::enable_from_other<T, U, U &&> * = nullptr, class U, detail::enable_from_other<T, U, U &&> * = nullptr,
detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr> detail::enable_if_t<!AuIsConvertible<U &&, T>::value> * = nullptr>
explicit optional(optional<U> &&rhs) explicit optional(optional<U> &&rhs)
{ {
if (rhs.has_value()) if (rhs.has_value())
@ -1781,7 +1778,7 @@ namespace tl {
/// one. /// one.
template <class... Args> T &emplace(Args &&... args) template <class... Args> T &emplace(Args &&... args)
{ {
static_assert(std::is_constructible<T, Args &&...>::value, static_assert(AuIsConstructible<T, Args &&...>::value,
"T must be constructible with Args"); "T must be constructible with Args");
*this = nullopt; *this = nullopt;
@ -1791,7 +1788,7 @@ namespace tl {
template <class U, class... Args> template <class U, class... Args>
detail::enable_if_t< detail::enable_if_t<
std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value, AuIsConstructible<T, std::initializer_list<U> &, Args &&...>::value,
T &> T &>
emplace(std::initializer_list<U> il, Args &&... args) emplace(std::initializer_list<U> il, Args &&... args)
{ {
@ -1806,7 +1803,7 @@ namespace tl {
/// If both have a value, the values are swapped. /// If both have a value, the values are swapped.
/// If one has a value, it is moved to the other and the movee is left /// If one has a value, it is moved to the other and the movee is left
/// valueless. /// valueless.
void swap(optional &rhs) noexcept(std::is_nothrow_move_constructible<T>::value void swap(optional &rhs) noexcept(AuIsNothrowMoveConstructible<T>::value
&&detail::is_nothrow_swappable<T>::value) &&detail::is_nothrow_swappable<T>::value)
{ {
using std::swap; using std::swap;
@ -1830,7 +1827,7 @@ namespace tl {
swap(this->m_has_value, rhs.m_has_value); swap(this->m_has_value, rhs.m_has_value);
} }
void Swap(optional &rhs) noexcept(std::is_nothrow_move_constructible<T>::value void Swap(optional &rhs) noexcept(AuIsNothrowMoveConstructible<T>::value
&&detail::is_nothrow_swappable<T>::value) &&detail::is_nothrow_swappable<T>::value)
{ {
using std::swap; using std::swap;
@ -1964,16 +1961,16 @@ namespace tl {
/// Returns the stored value if there is one, otherwise returns `u` /// Returns the stored value if there is one, otherwise returns `u`
template <class U> constexpr T value_or(U &&u) const & template <class U> constexpr T value_or(U &&u) const &
{ {
static_assert(std::is_copy_constructible<T>::value && static_assert(AuIsCopyConstructible<T>::value &&
std::is_convertible<U &&, T>::value, AuIsConvertible<U &&, T>::value,
"T must be copy constructible and convertible from U"); "T must be copy constructible and convertible from U");
return has_value() ? **this : static_cast<T>(AuForward<U>(u)); return has_value() ? **this : static_cast<T>(AuForward<U>(u));
} }
template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) &&
{ {
static_assert(std::is_move_constructible<T>::value && static_assert(AuIsMoveConstructible<T>::value &&
std::is_convertible<U &&, T>::value, AuIsConvertible<U &&, T>::value,
"T must be move constructible and convertible from U"); "T must be move constructible and convertible from U");
return has_value() ? AuMove(**this) : static_cast<T>(AuForward<U>(u)); return has_value() ? AuMove(**this) : static_cast<T>(AuForward<U>(u));
} }
@ -1981,16 +1978,16 @@ namespace tl {
/// Returns the stored value if there is one, otherwise returns `u` /// Returns the stored value if there is one, otherwise returns `u`
template <class U> constexpr T ValueOr(U &&u) const & template <class U> constexpr T ValueOr(U &&u) const &
{ {
static_assert(std::is_copy_constructible<T>::value && static_assert(AuIsCopyConstructible<T>::value &&
std::is_convertible<U &&, T>::value, AuIsConvertible<U &&, T>::value,
"T must be copy constructible and convertible from U"); "T must be copy constructible and convertible from U");
return has_value() ? **this : static_cast<T>(AuForward<U>(u)); return has_value() ? **this : static_cast<T>(AuForward<U>(u));
} }
template <class U> TL_OPTIONAL_11_CONSTEXPR T ValueOr(U &&u) && template <class U> TL_OPTIONAL_11_CONSTEXPR T ValueOr(U &&u) &&
{ {
static_assert(std::is_move_constructible<T>::value && static_assert(AuIsMoveConstructible<T>::value &&
std::is_convertible<U &&, T>::value, AuIsConvertible<U &&, T>::value,
"T must be move constructible and convertible from U"); "T must be move constructible and convertible from U");
return has_value() ? AuMove(**this) : static_cast<T>(AuForward<U>(u)); return has_value() ? AuMove(**this) : static_cast<T>(AuForward<U>(u));
} }
@ -2186,7 +2183,7 @@ namespace tl {
} }
template <class T, template <class T,
detail::enable_if_t<std::is_move_constructible<T>::value> * = nullptr, detail::enable_if_t<AuIsMoveConstructible<T>::value> * = nullptr,
detail::enable_if_t<detail::is_swappable<T>::value> * = nullptr> detail::enable_if_t<detail::is_swappable<T>::value> * = nullptr>
void swap(optional<T> &lhs, void swap(optional<T> &lhs,
optional<T> &rhs) noexcept(noexcept(lhs.swap(rhs))) optional<T> &rhs) noexcept(noexcept(lhs.swap(rhs)))
@ -2201,7 +2198,7 @@ namespace tl {
template <class T = detail::i_am_secret, class U, template <class T = detail::i_am_secret, class U,
class Ret = class Ret =
detail::conditional_t<std::is_same<T, detail::i_am_secret>::value, detail::conditional_t<AuIsSame<T, detail::i_am_secret>::value,
detail::decay_t<U>, T>> detail::decay_t<U>, T>>
inline constexpr optional<Ret> make_optional(U &&v) inline constexpr optional<Ret> make_optional(U &&v)
{ {
@ -2230,7 +2227,7 @@ namespace tl {
template <class Opt, class F, template <class Opt, class F,
class Ret = decltype(detail::invoke(AuDecalVal<F>(), class Ret = decltype(detail::invoke(AuDecalVal<F>(),
*AuDecalVal<Opt>())), *AuDecalVal<Opt>())),
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr> detail::enable_if_t<!AuIsVoid<Ret>::value> * = nullptr>
constexpr auto optional_map_impl(Opt &&opt, F &&f) constexpr auto optional_map_impl(Opt &&opt, F &&f)
{ {
return opt.has_value() return opt.has_value()
@ -2241,7 +2238,7 @@ namespace tl {
template <class Opt, class F, template <class Opt, class F,
class Ret = decltype(detail::invoke(AuDecalVal<F>(), class Ret = decltype(detail::invoke(AuDecalVal<F>(),
*AuDecalVal<Opt>())), *AuDecalVal<Opt>())),
detail::enable_if_t<std::is_void<Ret>::value> * = nullptr> detail::enable_if_t<AuIsVoid<Ret>::value> * = nullptr>
auto optional_map_impl(Opt &&opt, F &&f) auto optional_map_impl(Opt &&opt, F &&f)
{ {
if (opt.has_value()) if (opt.has_value())
@ -2256,7 +2253,7 @@ namespace tl {
template <class Opt, class F, template <class Opt, class F,
class Ret = decltype(detail::invoke(AuDecalVal<F>(), class Ret = decltype(detail::invoke(AuDecalVal<F>(),
*AuDecalVal<Opt>())), *AuDecalVal<Opt>())),
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr> detail::enable_if_t<!AuIsVoid<Ret>::value> * = nullptr>
constexpr auto optional_map_impl(Opt &&opt, F &&f) -> optional<Ret> constexpr auto optional_map_impl(Opt &&opt, F &&f) -> optional<Ret>
{ {
@ -2268,7 +2265,7 @@ namespace tl {
template <class Opt, class F, template <class Opt, class F,
class Ret = decltype(detail::invoke(AuDecalVal<F>(), class Ret = decltype(detail::invoke(AuDecalVal<F>(),
*AuDecalVal<Opt>())), *AuDecalVal<Opt>())),
detail::enable_if_t<std::is_void<Ret>::value> * = nullptr> detail::enable_if_t<AuIsVoid<Ret>::value> * = nullptr>
auto optional_map_impl(Opt &&opt, F &&f) -> optional<monostate> auto optional_map_impl(Opt &&opt, F &&f) -> optional<monostate>
{ {
@ -2813,14 +2810,14 @@ namespace tl {
/// Returns `u` if `*this` has a value, otherwise an empty optional. /// Returns `u` if `*this` has a value, otherwise an empty optional.
template <class U> template <class U>
constexpr optional<typename std::decay<U>::type> conjunction(U &&u) const constexpr optional<typename AuDecay<U>::type> conjunction(U &&u) const
{ {
using result = optional<detail::decay_t<U>>; using result = optional<detail::decay_t<U>>;
return has_value() ? result{u} : result { nullopt }; return has_value() ? result{u} : result { nullopt };
} }
template <class U> template <class U>
constexpr optional<typename std::decay<U>::type> Conjunction(U &&u) const constexpr optional<typename AuDecay<U>::type> Conjunction(U &&u) const
{ {
using result = optional<detail::decay_t<U>>; using result = optional<detail::decay_t<U>>;
return has_value() ? result{u} : result { nullopt }; return has_value() ? result{u} : result { nullopt };
@ -2990,7 +2987,7 @@ namespace tl {
* = nullptr> * = nullptr>
optional &operator=(U &&u) optional &operator=(U &&u)
{ {
static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue"); static_assert(AuIsLValueReference_v<U>, "U must be an lvalue");
m_value = std::addressof(u); m_value = std::addressof(u);
return *this; return *this;
} }
@ -3092,8 +3089,8 @@ namespace tl {
/// Returns the stored value if there is one, otherwise returns `u` /// Returns the stored value if there is one, otherwise returns `u`
template <class U> constexpr T value_or(U &&u) const &noexcept template <class U> constexpr T value_or(U &&u) const &noexcept
{ {
static_assert(std::is_copy_constructible<T>::value && static_assert(AuIsCopyConstructible<T>::value &&
std::is_convertible<U &&, T>::value, AuIsConvertible<U &&, T>::value,
"T must be copy constructible and convertible from U"); "T must be copy constructible and convertible from U");
return has_value() ? **this : static_cast<T>(AuForward<U>(u)); return has_value() ? **this : static_cast<T>(AuForward<U>(u));
} }
@ -3101,8 +3098,8 @@ namespace tl {
/// \group value_or /// \group value_or
template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && noexcept template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && noexcept
{ {
static_assert(std::is_move_constructible<T>::value && static_assert(AuIsMoveConstructible<T>::value &&
std::is_convertible<U &&, T>::value, AuIsConvertible<U &&, T>::value,
"T must be move constructible and convertible from U"); "T must be move constructible and convertible from U");
return has_value() ? **this : static_cast<T>(AuForward<U>(u)); return has_value() ? **this : static_cast<T>(AuForward<U>(u));
} }
@ -3110,8 +3107,8 @@ namespace tl {
/// Returns the stored value if there is one, otherwise returns `u` /// Returns the stored value if there is one, otherwise returns `u`
template <class U> constexpr T ValueOr(U &&u) const &noexcept template <class U> constexpr T ValueOr(U &&u) const &noexcept
{ {
static_assert(std::is_copy_constructible<T>::value && static_assert(AuIsCopyConstructible<T>::value &&
std::is_convertible<U &&, T>::value, AuIsConvertible<U &&, T>::value,
"T must be copy constructible and convertible from U"); "T must be copy constructible and convertible from U");
return has_value() ? **this : static_cast<T>(AuForward<U>(u)); return has_value() ? **this : static_cast<T>(AuForward<U>(u));
} }
@ -3119,8 +3116,8 @@ namespace tl {
/// \group value_or /// \group value_or
template <class U> TL_OPTIONAL_11_CONSTEXPR T ValueOr(U &&u) && noexcept template <class U> TL_OPTIONAL_11_CONSTEXPR T ValueOr(U &&u) && noexcept
{ {
static_assert(std::is_move_constructible<T>::value && static_assert(AuIsMoveConstructible<T>::value &&
std::is_convertible<U &&, T>::value, AuIsConvertible<U &&, T>::value,
"T must be move constructible and convertible from U"); "T must be move constructible and convertible from U");
return has_value() ? **this : static_cast<T>(AuForward<U>(u)); return has_value() ? **this : static_cast<T>(AuForward<U>(u));
} }
@ -3153,7 +3150,7 @@ namespace std
{ {
template <class T> struct hash<tl::optional<T>> template <class T> struct hash<tl::optional<T>>
{ {
::std::size_t operator()(const tl::optional<T> &o) const AuUInt operator()(const tl::optional<T> &o) const
{ {
if (!o.has_value()) if (!o.has_value())
return 0; return 0;

View File

@ -322,6 +322,7 @@ inline AUROXTL_CONSTEXPR bool AuIsArray_v<T[]> = true;
template <bool Test, class T = void> template <bool Test, class T = void>
using AuEnableIf_t = typename AuEnableIf<Test, T>::type; using AuEnableIf_t = typename AuEnableIf<Test, T>::type;
#if !defined(AURORA_COMPILER_CLANG) && !defined(AURORA_COMPILER_MSVC)
template <class T, class ... Args> template <class T, class ... Args>
struct AuIsConstructible struct AuIsConstructible
{ {
@ -333,6 +334,17 @@ struct AuIsConstructible
template <class T, class ... Args> template <class T, class ... Args>
using AuIsConstructible_t = typename AuIsConstructible<T, Args ...>::type; using AuIsConstructible_t = typename AuIsConstructible<T, Args ...>::type;
#else
template <class T, class ... Args>
struct AuIsConstructible : AuBoolType<__is_constructible(T, Args...)>
{
};
template <class T, class ... Args>
using AuIsConstructible_t = typename AuIsConstructible<T, Args ...>::type;
#endif
template <class T, class ... Args> template <class T, class ... Args>
inline AUROXTL_CONSTEXPR bool AuIsConstructible_v = AuIsConstructible<T, Args ...>::type::value; inline AUROXTL_CONSTEXPR bool AuIsConstructible_v = AuIsConstructible<T, Args ...>::type::value;
@ -593,6 +605,18 @@ namespace _audetail
} }
} }
#endif #endif
template<class T>
auto test_returnable(int) -> decltype(void(static_cast<T(*)()>(nullptr)), AuTrueType {});
template<class>
auto test_returnable(...) -> AuFalseType;
template<class From, class To>
auto test_implicitly_convertible(int) -> decltype(void(AuDeclType<void(&)(To)>()(AuDeclType<From>())), AuTrueType {});
template<class, class>
auto test_implicitly_convertible(...) -> AuFalseType;
} }
template <class T, class T2> template <class T, class T2>
@ -624,4 +648,175 @@ using AuCommonType_t = typename _audetail::common_type<T, T2>::type;
return AuForward<F>(std::invoke(f, AuForward<Args>(args)...)); return AuForward<F>(std::invoke(f, AuForward<Args>(args)...));
} }
#endif #endif
template <class T, class Z>
struct AuIsAssignable : AuBoolType<__is_assignable(T, Z)>
{ };
template <class T, class Z>
constexpr bool AuIsAssignable_v = AuIsAssignable<T, Z>::value;
template <class T>
struct AuIsCopyAssignable : AuIsAssignable<AuAddLReference_t<T>, AuAddRReference_t<const T>>
{ };
template <class T>
constexpr bool AuIsCopyAssignable_v = AuIsCopyAssignable<T>::value;
template<class T>
struct AuIsMoveAssignable : AuIsAssignable<AuAddLReference_t<T>, AuAddRReference_t<T>>
{ };
template <class T>
constexpr bool AuIsMoveAssignable_v = AuIsMoveAssignable<T>::value;
template <class T, class Z>
struct AuIsTriviallyAssignable : AuBoolType<__is_trivially_assignable(T, Z)>
{ };
template <class T, class Z>
constexpr bool AuIsTriviallyAssignable_v = AuIsTriviallyAssignable<T, Z>::value;
template<class T>
struct AuIsTriviallyCopyAssignable
: AuIsTriviallyAssignable<AuAddLReference_t<T>, AuAddRReference_t<const T>>
{ };
template<class T>
constexpr bool AuIsTriviallyCopyAssignable_v = AuIsTriviallyCopyAssignable<T>::value;
template<class T>
struct AuIsTriviallyMoveAssignable
: AuIsTriviallyAssignable<AuAddLReference_t<T>, AuAddRReference_t<T>>
{ };
template<class T>
constexpr bool AuIsTriviallyMoveAssignable_v = AuIsTriviallyMoveAssignable<T>::value;
template <class T>
struct AuIsMoveConstructible : AuIsConstructible<T, T>
{ };
template <class T>
constexpr bool AuIsMoveConstructible_v = AuIsMoveConstructible<T>::value;
template <class T>
struct AuIsCopyConstructible : AuIsConstructible<T, AuAddLReference_t<const T>>
{ };
template <class T>
constexpr bool AuIsCopyConstructible_v = AuIsCopyConstructible<T>::value;
template <class T>
struct AuIsDefaultConstructible : AuIsConstructible<T>
{ };
template <class T>
constexpr bool AuIsDefaultConstructible_v = AuIsDefaultConstructible<T>::value;
template <class T>
struct AuIsTriviallyDestructible : AuBoolType<__is_trivially_destructible(T)>
{ };
template <class T>
constexpr bool AuIsTriviallyDestructible_v = AuIsTriviallyDestructible<T>::value;
//template<class From, class To>
//struct AuIsConvertible : AuBoolType<
// (decltype(_audetail::test_returnable<To>(0))::value &&
// decltype(_audetail::test_implicitly_convertible<From, To>(0))::value) ||
// (AuIsVoid<From>::value && AuIsVoid<To>::value)
//>
//{ };
template<class From, class To>
struct AuIsConvertible : AuBoolType<__is_convertible_to(From, To)>
{ };
template <class T, class Z>
constexpr bool AuIsConvertible_v = AuIsConvertible<T, Z>::value;
template <class T, class Z>
struct AuIsNothrowAssignable : AuBoolType<__is_nothrow_assignable(T, Z)>
{ };
template <class T, class Z>
constexpr bool AuIsNothrowAssignable_v = AuIsNothrowAssignable<T, Z>::value;
template <class T>
struct AuIsNothrowCopyAssignable : AuIsNothrowAssignable<AuAddLReference_t<T>, AuAddLReference_t<const T>>
{ };
template <class T>
constexpr bool AuIsNothrowCopyAssignable_v = AuIsNothrowCopyAssignable<T>::value;
template <class T>
struct AuIsNothrowMoveAssignable : AuIsNothrowAssignable<AuAddLReference_t<T>, T>
{ };
template <class T>
constexpr bool AuIsNothrowMoveAssignable_v = AuIsNothrowMoveAssignable<T>::value;
template <class T>
struct AuIsTriviallyCopyable : AuBoolType<__is_trivially_copyable(T)>
{ };
template <class T>
constexpr bool AuIsTriviallyCopyable_v = AuIsTriviallyCopyable<T>::value;
template <class T, class ... Args>
struct AuIsTriviallyConstructible : AuBoolType<__is_trivially_constructible(T, Args...)>
{ };
template <class T, class ... Args>
constexpr bool AuIsTriviallyConstructible_v = AuIsTriviallyConstructible<T, Args...>::value;
template <class T>
struct AuIsTriviallyMoveConstructible : AuIsTriviallyConstructible<T, T>
{ };
template <class T>
constexpr bool AuIsTriviallyMoveConstructible_v = AuIsTriviallyMoveConstructible<T>::value;
template <class T>
struct AuIsTriviallyCopyConstructible : AuIsTriviallyConstructible<T, AuAddLReference_t<const T>>
{ };
template <class T>
constexpr bool AuIsTriviallyCopyConstructible_v = AuIsTriviallyCopyConstructible<T>::value;
template <class T>
struct AuIsTriviallyDefaultConstructible : AuIsTriviallyConstructible<T>
{ };
template <class T>
constexpr bool AuIsTriviallyDefaultConstructible_v = AuIsTriviallyDefaultConstructible<T>::value;
template <class T, class ... Args>
struct AuIsNothrowConstructible : AuBoolType<__is_nothrow_constructible(T, Args...)>
{ };
template <class T, class ... Args>
constexpr bool AuIsNothrowConstructible_v = AuIsNothrowConstructible<T, Args...>::value;
template <class T>
struct AuIsNothrowMoveConstructible : AuIsNothrowConstructible<T, T>
{ };
template <class T>
constexpr bool AuIsNothrowMoveConstructible_v = AuIsNothrowMoveConstructible<T>::value;
template <class T>
struct AuIsNothrowCopyConstructible : AuIsNothrowConstructible<T, AuAddLReference_t<const T>>
{ };
template <class T>
constexpr bool AuIsNothrowCopyConstructible_v = AuIsNothrowCopyConstructible<T>::value;
template <class T>
struct AuIsNothrowDefaultConstructible : AuIsNothrowConstructible<T>
{ };
template <class T>
constexpr bool AuIsNothrowDefaultConstructible_v = AuIsNothrowDefaultConstructible<T>::value;