[*] 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
// 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
// for non-copyable types
@ -84,13 +84,13 @@ namespace tl {
tl::detail::is_trivially_copy_constructible<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
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
#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) \
std::is_trivially_copy_assignable<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
AuIsTriviallyCopyAssignable<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) AuIsTriviallyDestructible<T>::value
#endif
#if __cplusplus > 201103L
@ -127,10 +127,10 @@ namespace tl {
#ifndef TL_TRAITS_MUTEX
#define TL_TRAITS_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_const_t = typename AuRemoveConst<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;
using remove_reference_t = typename AuRemoveReference<T>::type;
template <class T> using decay_t = typename AuDecay<T>::type;
template <bool E, class T = void>
using enable_if_t = typename AuEnableIf<E, T>::type;
template <bool B, class T, class F>
@ -241,7 +241,7 @@ namespace tl {
{ };
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
// becomes std::swap
@ -253,40 +253,38 @@ namespace tl {
template <class, class> AuFalseType uses_std(...);
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);
template <class T>
struct is_std_swap_noexcept
: std::integral_constant<bool,
std::is_nothrow_move_constructible<T>::value &&
std::is_nothrow_move_assignable<T>::value>
: AuBoolType<
AuIsNothrowMoveConstructible<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>
{ };
template <class T, class U>
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
template <class T, class U = T>
struct is_swappable
: std::integral_constant<
bool,
: AuBoolType<
decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
(!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
(std::is_move_assignable<T>::value &&
std::is_move_constructible<T>::value))>
(AuIsMoveAssignable<T>::value &&
AuIsMoveConstructible<T>::value))>
{ };
template <class T, std::size_t N>
template <class T, AuUInt N>
struct is_swappable<T[N], T[N]>
: std::integral_constant<
bool,
: AuBoolType<
decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
(!decltype(
detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value ||
@ -295,8 +293,7 @@ namespace tl {
template <class T, class U = T>
struct is_nothrow_swappable
: std::integral_constant<
bool,
: AuBoolType<
is_swappable<T, U>::value &&
((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value
&&detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||
@ -323,7 +320,7 @@ namespace tl {
// Change void to tl::monostate
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>>
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... 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>
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>
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>;
detail::enable_if_t<AuIsConstructible<T, U &&>::value &&
!AuIsSame<detail::decay_t<U>, in_place_t>::value &&
!AuIsSame<optional<T>, detail::decay_t<U>>::value>;
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 &&
!std::is_constructible<T, const optional<U> &>::value &&
!std::is_constructible<T, const optional<U> &&>::value &&
!std::is_convertible<optional<U> &, T>::value &&
!std::is_convertible<optional<U> &&, T>::value &&
!std::is_convertible<const optional<U> &, T>::value &&
!std::is_convertible<const optional<U> &&, T>::value>;
AuIsConstructible<T, Other>::value &&
!AuIsConstructible<T, optional<U> &>::value &&
!AuIsConstructible<T, optional<U> &&>::value &&
!AuIsConstructible<T, const optional<U> &>::value &&
!AuIsConstructible<T, const optional<U> &&>::value &&
!AuIsConvertible<optional<U> &, T>::value &&
!AuIsConvertible<optional<U> &&, T>::value &&
!AuIsConvertible<const optional<U> &, T>::value &&
!AuIsConvertible<const optional<U> &&, T>::value>;
template <class T, class U>
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>,
std::is_same<T, detail::decay_t<U>>>::value &&
std::is_constructible<T, U>::value &&std::is_assignable<T &, U>::value>;
AuIsSame<T, detail::decay_t<U>>>::value &&
AuIsConstructible<T, U>::value &&AuIsAssignable<T &, U>::value>;
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 &&
!std::is_constructible<T, optional<U> &&>::value &&
!std::is_constructible<T, const optional<U> &>::value &&
!std::is_constructible<T, const optional<U> &&>::value &&
!std::is_convertible<optional<U> &, T>::value &&
!std::is_convertible<optional<U> &&, T>::value &&
!std::is_convertible<const optional<U> &, T>::value &&
!std::is_convertible<const optional<U> &&, T>::value &&
!std::is_assignable<T &, optional<U> &>::value &&
!std::is_assignable<T &, optional<U> &&>::value &&
!std::is_assignable<T &, const optional<U> &>::value &&
!std::is_assignable<T &, const optional<U> &&>::value>;
AuIsConstructible<T, Other>::value &&
AuIsAssignable<T &, Other>::value &&
!AuIsConstructible<T, optional<U> &>::value &&
!AuIsConstructible<T, optional<U> &&>::value &&
!AuIsConstructible<T, const optional<U> &>::value &&
!AuIsConstructible<T, const optional<U> &&>::value &&
!AuIsConvertible<optional<U> &, T>::value &&
!AuIsConvertible<optional<U> &&, T>::value &&
!AuIsConvertible<const optional<U> &, T>::value &&
!AuIsConvertible<const optional<U> &&, T>::value &&
!AuIsAssignable<T &, optional<U> &>::value &&
!AuIsAssignable<T &, optional<U> &&>::value &&
!AuIsAssignable<T &, const optional<U> &>::value &&
!AuIsAssignable<T &, const optional<U> &&>::value>;
// The storage base manages the actual storage, and correctly propagates
// trivial destruction from T. This case is for when T is not trivially
// destructible.
template <class T, bool = ::std::is_trivially_destructible<T>::value>
template <class T, bool = AuIsTriviallyDestructible<T>::value>
struct optional_storage_base
{
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
// move constructible
#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>
{
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(optional_move_base &&rhs) noexcept(
std::is_nothrow_move_constructible<T>::value)
AuIsNothrowMoveConstructible<T>::value)
{
if (rhs.has_value())
{
@ -608,13 +605,13 @@ namespace tl {
// This class manages conditionally having a trivial move assignment operator
// 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
// move assignable
#ifndef TL_OPTIONAL_GCC49
template <class T, bool = std::is_trivially_destructible<T>::value
&&std::is_trivially_move_constructible<T>::value
&&std::is_trivially_move_assignable<T>::value>
template <class T, bool = AuIsTriviallyDestructible<T>::value
&&AuIsTriviallyMoveConstructible<T>::value
&&AuIsTriviallyMoveAssignable<T>::value>
struct optional_move_assign_base : optional_copy_assign_base<T>
{
using optional_copy_assign_base<T>::optional_copy_assign_base;
@ -638,8 +635,8 @@ namespace tl {
optional_move_assign_base &
operator=(optional_move_assign_base &&rhs) noexcept(
std::is_nothrow_move_constructible<T>::value
&&std::is_nothrow_move_assignable<T>::value)
AuIsNothrowMoveConstructible<T>::value
&&AuIsNothrowMoveAssignable<T>::value)
{
this->assign(AuMove(rhs));
return *this;
@ -648,8 +645,8 @@ namespace tl {
// 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>
template <class T, bool EnableCopy = AuIsCopyConstructible<T>::value,
bool EnableMove = AuIsMoveConstructible<T>::value>
struct optional_delete_ctor_base
{
optional_delete_ctor_base() = default;
@ -697,10 +694,10 @@ namespace tl {
// 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)>
bool EnableCopy = (AuIsCopyConstructible<T>::value &&
AuIsCopyAssignable<T>::value),
bool EnableMove = (AuIsMoveConstructible<T>::value &&
AuIsMoveAssignable<T>::value)>
struct optional_delete_assign_base
{
optional_delete_assign_base() = default;
@ -786,9 +783,9 @@ namespace tl {
{
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");
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");
public:
@ -1457,14 +1454,14 @@ namespace tl {
/// Returns `u` if `*this` has a value, otherwise an empty optional.
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>>;
return has_value() ? result{u} : result { nullopt };
}
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>>;
return has_value() ? result{u} : result { nullopt };
@ -1599,14 +1596,14 @@ namespace tl {
/// Constructs the stored value in-place using the given arguments.
template <class... Args>
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)
: base(in_place, AuForward<Args>(args)...)
{ }
template <class U, class... Args>
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,
in_place_t>,
std::initializer_list<U> il, Args &&... args)
@ -1617,14 +1614,14 @@ namespace tl {
/// Constructs the stored value with `u`.
template <
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>
constexpr optional(U &&u) : base(in_place, AuForward<U>(u))
{ }
template <
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>
constexpr explicit optional(U &&u) : base(in_place, AuForward<U>(u))
{ }
@ -1632,7 +1629,7 @@ namespace tl {
/// Converting copy constructor.
template <
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)
{
if (rhs.has_value())
@ -1642,7 +1639,7 @@ namespace tl {
}
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>
explicit optional(const optional<U> &rhs)
{
@ -1655,7 +1652,7 @@ namespace tl {
/// Converting move constructor.
template <
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)
{
if (rhs.has_value())
@ -1666,7 +1663,7 @@ namespace tl {
template <
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)
{
if (rhs.has_value())
@ -1781,7 +1778,7 @@ namespace tl {
/// one.
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");
*this = nullopt;
@ -1791,7 +1788,7 @@ namespace tl {
template <class U, class... Args>
detail::enable_if_t<
std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value,
AuIsConstructible<T, std::initializer_list<U> &, Args &&...>::value,
T &>
emplace(std::initializer_list<U> il, Args &&... args)
{
@ -1806,7 +1803,7 @@ namespace tl {
/// 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
/// 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)
{
using std::swap;
@ -1830,7 +1827,7 @@ namespace tl {
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)
{
using std::swap;
@ -1964,16 +1961,16 @@ namespace tl {
/// Returns the stored value if there is one, otherwise returns `u`
template <class U> constexpr T value_or(U &&u) const &
{
static_assert(std::is_copy_constructible<T>::value &&
std::is_convertible<U &&, T>::value,
static_assert(AuIsCopyConstructible<T>::value &&
AuIsConvertible<U &&, T>::value,
"T must be copy constructible and convertible from U");
return has_value() ? **this : static_cast<T>(AuForward<U>(u));
}
template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) &&
{
static_assert(std::is_move_constructible<T>::value &&
std::is_convertible<U &&, T>::value,
static_assert(AuIsMoveConstructible<T>::value &&
AuIsConvertible<U &&, T>::value,
"T must be move constructible and convertible from 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`
template <class U> constexpr T ValueOr(U &&u) const &
{
static_assert(std::is_copy_constructible<T>::value &&
std::is_convertible<U &&, T>::value,
static_assert(AuIsCopyConstructible<T>::value &&
AuIsConvertible<U &&, T>::value,
"T must be copy constructible and convertible from U");
return has_value() ? **this : static_cast<T>(AuForward<U>(u));
}
template <class U> TL_OPTIONAL_11_CONSTEXPR T ValueOr(U &&u) &&
{
static_assert(std::is_move_constructible<T>::value &&
std::is_convertible<U &&, T>::value,
static_assert(AuIsMoveConstructible<T>::value &&
AuIsConvertible<U &&, T>::value,
"T must be move constructible and convertible from U");
return has_value() ? AuMove(**this) : static_cast<T>(AuForward<U>(u));
}
@ -2186,7 +2183,7 @@ namespace tl {
}
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>
void swap(optional<T> &lhs,
optional<T> &rhs) noexcept(noexcept(lhs.swap(rhs)))
@ -2201,7 +2198,7 @@ namespace tl {
template <class T = detail::i_am_secret, class U,
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>>
inline constexpr optional<Ret> make_optional(U &&v)
{
@ -2230,7 +2227,7 @@ namespace tl {
template <class Opt, class F,
class Ret = decltype(detail::invoke(AuDecalVal<F>(),
*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)
{
return opt.has_value()
@ -2241,7 +2238,7 @@ namespace tl {
template <class Opt, class F,
class Ret = decltype(detail::invoke(AuDecalVal<F>(),
*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)
{
if (opt.has_value())
@ -2256,7 +2253,7 @@ namespace tl {
template <class Opt, class F,
class Ret = decltype(detail::invoke(AuDecalVal<F>(),
*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>
{
@ -2268,7 +2265,7 @@ namespace tl {
template <class Opt, class F,
class Ret = decltype(detail::invoke(AuDecalVal<F>(),
*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>
{
@ -2813,14 +2810,14 @@ namespace tl {
/// Returns `u` if `*this` has a value, otherwise an empty optional.
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>>;
return has_value() ? result{u} : result { nullopt };
}
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>>;
return has_value() ? result{u} : result { nullopt };
@ -2990,7 +2987,7 @@ namespace tl {
* = nullptr>
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);
return *this;
}
@ -3092,8 +3089,8 @@ namespace tl {
/// Returns the stored value if there is one, otherwise returns `u`
template <class U> constexpr T value_or(U &&u) const &noexcept
{
static_assert(std::is_copy_constructible<T>::value &&
std::is_convertible<U &&, T>::value,
static_assert(AuIsCopyConstructible<T>::value &&
AuIsConvertible<U &&, T>::value,
"T must be copy constructible and convertible from U");
return has_value() ? **this : static_cast<T>(AuForward<U>(u));
}
@ -3101,8 +3098,8 @@ namespace tl {
/// \group value_or
template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && noexcept
{
static_assert(std::is_move_constructible<T>::value &&
std::is_convertible<U &&, T>::value,
static_assert(AuIsMoveConstructible<T>::value &&
AuIsConvertible<U &&, T>::value,
"T must be move constructible and convertible from 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`
template <class U> constexpr T ValueOr(U &&u) const &noexcept
{
static_assert(std::is_copy_constructible<T>::value &&
std::is_convertible<U &&, T>::value,
static_assert(AuIsCopyConstructible<T>::value &&
AuIsConvertible<U &&, T>::value,
"T must be copy constructible and convertible from U");
return has_value() ? **this : static_cast<T>(AuForward<U>(u));
}
@ -3119,8 +3116,8 @@ namespace tl {
/// \group value_or
template <class U> TL_OPTIONAL_11_CONSTEXPR T ValueOr(U &&u) && noexcept
{
static_assert(std::is_move_constructible<T>::value &&
std::is_convertible<U &&, T>::value,
static_assert(AuIsMoveConstructible<T>::value &&
AuIsConvertible<U &&, T>::value,
"T must be move constructible and convertible from 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>>
{
::std::size_t operator()(const tl::optional<T> &o) const
AuUInt operator()(const tl::optional<T> &o) const
{
if (!o.has_value())
return 0;

View File

@ -322,6 +322,7 @@ inline AUROXTL_CONSTEXPR bool AuIsArray_v<T[]> = true;
template <bool Test, class T = void>
using AuEnableIf_t = typename AuEnableIf<Test, T>::type;
#if !defined(AURORA_COMPILER_CLANG) && !defined(AURORA_COMPILER_MSVC)
template <class T, class ... Args>
struct AuIsConstructible
{
@ -333,6 +334,17 @@ struct AuIsConstructible
template <class T, class ... Args>
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>
inline AUROXTL_CONSTEXPR bool AuIsConstructible_v = AuIsConstructible<T, Args ...>::type::value;
@ -593,6 +605,18 @@ namespace _audetail
}
}
#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>
@ -625,3 +649,174 @@ using AuCommonType_t = typename _audetail::common_type<T, T2>::type;
}
#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;