fix(templates): fix requirements for FAny and TAtomic

This commit is contained in:
_Redstone_c_ 2022-12-16 19:30:55 +08:00
parent a8e1852b34
commit 441df3791c
4 changed files with 72 additions and 58 deletions

View File

@ -21,6 +21,13 @@ NAMESPACE_MODULE_BEGIN(Utility)
// 3) it is less exception-safe // 3) it is less exception-safe
// But we don't follow the the copy-and-swap idiom, because we assume that no function throws an exception. // But we don't follow the the copy-and-swap idiom, because we assume that no function throws an exception.
NAMESPACE_PRIVATE_BEGIN
template <typename T>
concept CFAnyPlaceable = CDestructible<TDecay<T>> && CCopyConstructible<TDecay<T>> && CMoveConstructible<TDecay<T>> && CSwappable<TDecay<T>>;
NAMESPACE_PRIVATE_END
class alignas(16) FAny class alignas(16) FAny
{ {
public: public:
@ -79,15 +86,14 @@ public:
} }
} }
template <typename T, typename... Ts> requires (CDestructible<TDecay<T>> template <typename T, typename... Ts> requires (NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CConstructibleFrom<TDecay<T>, Ts&&...>)
&& CConstructibleFrom<TDecay<T>, Ts&&...>)
FORCEINLINE explicit FAny(TInPlaceType<T>, Ts&&... Args) FORCEINLINE explicit FAny(TInPlaceType<T>, Ts&&... Args)
{ {
EmplaceImpl<T>(Forward<Ts>(Args)...); EmplaceImpl<T>(Forward<Ts>(Args)...);
} }
template <typename T> requires (!CBaseOf<FAny, TDecay<T>> && !CTInPlaceType<TDecay<T>> template <typename T> requires (!CBaseOf<FAny, TDecay<T>> && !CTInPlaceType<TDecay<T>>
&& CDestructible<TDecay<T>> && CConstructibleFrom<TDecay<T>, T&&>) && NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CConstructibleFrom<TDecay<T>, T&&>)
FORCEINLINE FAny(T&& InValue) : FAny(InPlaceType<TDecay<T>>, Forward<T>(InValue)) FORCEINLINE FAny(T&& InValue) : FAny(InPlaceType<TDecay<T>>, Forward<T>(InValue))
{ } { }
@ -213,7 +219,7 @@ public:
} }
template <typename T> requires (!CBaseOf<FAny, TDecay<T>> && !CTInPlaceType<TDecay<T>> template <typename T> requires (!CBaseOf<FAny, TDecay<T>> && !CTInPlaceType<TDecay<T>>
&& CDestructible<TDecay<T>>&& CConstructibleFrom<TDecay<T>, T&&>) && NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CConstructibleFrom<TDecay<T>, T&&>)
FORCEINLINE FAny& operator=(T&& InValue) FORCEINLINE FAny& operator=(T&& InValue)
{ {
using DecayedType = TDecay<T>; using DecayedType = TDecay<T>;
@ -231,8 +237,7 @@ public:
return *this; return *this;
} }
template <typename T, typename... Ts> requires (CDestructible<TDecay<T>> template <typename T, typename... Ts> requires (NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CConstructibleFrom<TDecay<T>, Ts&&...>)
&& CConstructibleFrom<TDecay<T>, Ts&&...>)
FORCEINLINE TDecay<T>& Emplace(Ts&&... Args) FORCEINLINE TDecay<T>& Emplace(Ts&&... Args)
{ {
Destroy(); Destroy();
@ -247,22 +252,22 @@ public:
template <typename T> FORCEINLINE constexpr bool HoldsAlternative() const { return IsValid() ? GetTypeInfo() == typeid(T) : false; } template <typename T> FORCEINLINE constexpr bool HoldsAlternative() const { return IsValid() ? GetTypeInfo() == typeid(T) : false; }
template <typename T> requires (CSameAs<T, TDecay<T>>&& CDestructible<TDecay<T>>) template <typename T> requires (CSameAs<T, TDecay<T>> && NAMESPACE_PRIVATE::CFAnyPlaceable<T>)
FORCEINLINE constexpr T& GetValue() & { checkf(HoldsAlternative<T>(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast< T*>(GetStorage()); } FORCEINLINE constexpr T& GetValue() & { checkf(HoldsAlternative<T>(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast< T*>(GetStorage()); }
template <typename T> requires (CSameAs<T, TDecay<T>>&& CDestructible<TDecay<T>>) template <typename T> requires (CSameAs<T, TDecay<T>> && NAMESPACE_PRIVATE::CFAnyPlaceable<T>)
FORCEINLINE constexpr T&& GetValue() && { checkf(HoldsAlternative<T>(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast< T*>(GetStorage())); } FORCEINLINE constexpr T&& GetValue() && { checkf(HoldsAlternative<T>(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast< T*>(GetStorage())); }
template <typename T> requires (CSameAs<T, TDecay<T>>&& CDestructible<TDecay<T>>) template <typename T> requires (CSameAs<T, TDecay<T>> && NAMESPACE_PRIVATE::CFAnyPlaceable<T>)
FORCEINLINE constexpr const T& GetValue() const& { checkf(HoldsAlternative<T>(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast<const T*>(GetStorage()); } FORCEINLINE constexpr const T& GetValue() const& { checkf(HoldsAlternative<T>(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast<const T*>(GetStorage()); }
template <typename T> requires (CSameAs<T, TDecay<T>>&& CDestructible<TDecay<T>>) template <typename T> requires (CSameAs<T, TDecay<T>> && NAMESPACE_PRIVATE::CFAnyPlaceable<T>)
FORCEINLINE constexpr const T&& GetValue() const&& { checkf(HoldsAlternative<T>(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast<const T*>(GetStorage())); } FORCEINLINE constexpr const T&& GetValue() const&& { checkf(HoldsAlternative<T>(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return MoveTemp(*reinterpret_cast<const T*>(GetStorage())); }
template <typename T> requires (CSameAs<T, TDecay<T>> && CDestructible<TDecay<T>>) template <typename T> requires (CSameAs<T, TDecay<T>> && NAMESPACE_PRIVATE::CFAnyPlaceable<T>)
FORCEINLINE constexpr T& Get( T& DefaultValue) & { return HoldsAlternative<T>() ? GetValue<T>() : DefaultValue; } FORCEINLINE constexpr T& Get( T& DefaultValue) & { return HoldsAlternative<T>() ? GetValue<T>() : DefaultValue; }
template <typename T> requires (CSameAs<T, TDecay<T>> && CDestructible<TDecay<T>>) template <typename T> requires (CSameAs<T, TDecay<T>> && NAMESPACE_PRIVATE::CFAnyPlaceable<T>)
FORCEINLINE constexpr const T& Get(const T& DefaultValue) const& { return HoldsAlternative<T>() ? GetValue<T>() : DefaultValue; } FORCEINLINE constexpr const T& Get(const T& DefaultValue) const& { return HoldsAlternative<T>() ? GetValue<T>() : DefaultValue; }
FORCEINLINE void Reset() FORCEINLINE void Reset()

View File

@ -229,10 +229,12 @@ protected:
NAMESPACE_PRIVATE_END NAMESPACE_PRIVATE_END
template <typename T> template <typename T> requires (CTriviallyCopyable<T>
&& CCopyConstructible<T> && CMoveConstructible<T>
&& CCopyAssignable<T> && CMoveAssignable<T>)
struct TAtomic : STRONG_INHERIT(NAMESPACE_PRIVATE::TAtomicImpl<T, false>); struct TAtomic : STRONG_INHERIT(NAMESPACE_PRIVATE::TAtomicImpl<T, false>);
template <typename T> template <typename T> requires (CTriviallyCopyable<T>)
struct TAtomicRef : STRONG_INHERIT(NAMESPACE_PRIVATE::TAtomicImpl<T, true>); struct TAtomicRef : STRONG_INHERIT(NAMESPACE_PRIVATE::TAtomicImpl<T, true>);
template <typename T> template <typename T>

View File

@ -11,27 +11,31 @@ NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility) NAMESPACE_MODULE_BEGIN(Utility)
template <typename OptionalType> requires (CDestructible<OptionalType>)
class TOptional;
NAMESPACE_PRIVATE_BEGIN
template <typename T, typename U>
concept CTOptionalAllowUnwrappable =
!(CConstructibleFrom<U, TOptional<T>& >
|| CConstructibleFrom<U, const TOptional<T>& >
|| CConstructibleFrom<U, TOptional<T>&&>
|| CConstructibleFrom<U, const TOptional<T>&&>
|| CConvertibleTo< TOptional<T>&, U>
|| CConvertibleTo<const TOptional<T>&, U>
|| CConvertibleTo< TOptional<T>&&, U>
|| CConvertibleTo<const TOptional<T>&&, U>
|| CAssignableFrom<U&, TOptional<T>& >
|| CAssignableFrom<U&, const TOptional<T>& >
|| CAssignableFrom<U&, TOptional<T>&&>
|| CAssignableFrom<U&, const TOptional<T>&&>);
NAMESPACE_PRIVATE_END
template <typename OptionalType> requires (CDestructible<OptionalType>) template <typename OptionalType> requires (CDestructible<OptionalType>)
class TOptional class TOptional
{ {
private:
template <typename T>
struct TAllowUnwrapping : TBoolConstant<!(
CConstructibleFrom<OptionalType, TOptional<T>& >
|| CConstructibleFrom<OptionalType, const TOptional<T>& >
|| CConstructibleFrom<OptionalType, TOptional<T>&&>
|| CConstructibleFrom<OptionalType, const TOptional<T>&&>
|| CConvertibleTo< TOptional<T>&, OptionalType>
|| CConvertibleTo<const TOptional<T>&, OptionalType>
|| CConvertibleTo< TOptional<T>&&, OptionalType>
|| CConvertibleTo<const TOptional<T>&&, OptionalType>
|| CAssignableFrom<OptionalType&, TOptional<T>& >
|| CAssignableFrom<OptionalType&, const TOptional<T>& >
|| CAssignableFrom<OptionalType&, TOptional<T>&&>
|| CAssignableFrom<OptionalType&, const TOptional<T>&&>
)> { };
public: public:
using ValueType = OptionalType; using ValueType = OptionalType;
@ -69,14 +73,14 @@ public:
if (InValue.IsValid()) new (&Value) OptionalType(MoveTemp(InValue.GetValue())); if (InValue.IsValid()) new (&Value) OptionalType(MoveTemp(InValue.GetValue()));
} }
template <typename T = OptionalType> requires (CConstructibleFrom<OptionalType, const T&> && TAllowUnwrapping<T>::Value) template <typename T = OptionalType> requires (CConstructibleFrom<OptionalType, const T&> && NAMESPACE_PRIVATE::CTOptionalAllowUnwrappable<T, OptionalType>)
FORCEINLINE constexpr explicit (!CConvertibleTo<const T&, OptionalType>) TOptional(const TOptional<T>& InValue) FORCEINLINE constexpr explicit (!CConvertibleTo<const T&, OptionalType>) TOptional(const TOptional<T>& InValue)
: bIsValid(InValue.IsValid()) : bIsValid(InValue.IsValid())
{ {
if (InValue.IsValid()) new (&Value) OptionalType(InValue.GetValue()); if (InValue.IsValid()) new (&Value) OptionalType(InValue.GetValue());
} }
template <typename T = OptionalType> requires (CConstructibleFrom<OptionalType, T&&> && TAllowUnwrapping<T>::Value) template <typename T = OptionalType> requires (CConstructibleFrom<OptionalType, T&&> && NAMESPACE_PRIVATE::CTOptionalAllowUnwrappable<T, OptionalType>)
FORCEINLINE constexpr explicit (!CConvertibleTo<T&&, OptionalType>) TOptional(TOptional<T>&& InValue) FORCEINLINE constexpr explicit (!CConvertibleTo<T&&, OptionalType>) TOptional(TOptional<T>&& InValue)
: bIsValid(InValue.IsValid()) : bIsValid(InValue.IsValid())
{ {
@ -137,7 +141,7 @@ public:
} }
template <typename T = OptionalType> requires (CConstructibleFrom<OptionalType, const T&> template <typename T = OptionalType> requires (CConstructibleFrom<OptionalType, const T&>
&& CAssignableFrom<OptionalType&, const T&> && TAllowUnwrapping<T>::Value) && CAssignableFrom<OptionalType&, const T&> && NAMESPACE_PRIVATE::CTOptionalAllowUnwrappable<T, OptionalType>)
FORCEINLINE constexpr TOptional& operator=(const TOptional<T>& InValue) FORCEINLINE constexpr TOptional& operator=(const TOptional<T>& InValue)
{ {
if (!InValue.IsValid()) if (!InValue.IsValid())
@ -157,7 +161,7 @@ public:
} }
template <typename T = OptionalType> requires (CConstructibleFrom<OptionalType, T&&> template <typename T = OptionalType> requires (CConstructibleFrom<OptionalType, T&&>
&& CAssignableFrom<OptionalType&, T&&> && TAllowUnwrapping<T>::Value) && CAssignableFrom<OptionalType&, T&&> && NAMESPACE_PRIVATE::CTOptionalAllowUnwrappable<T, OptionalType>)
FORCEINLINE constexpr TOptional& operator=(TOptional<T>&& InValue) FORCEINLINE constexpr TOptional& operator=(TOptional<T>&& InValue)
{ {
if (!InValue.IsValid()) if (!InValue.IsValid())

View File

@ -122,6 +122,25 @@ using TUnwrapReference = typename NAMESPACE_PRIVATE::TUnwrapReferenceImpl<T>::Ty
template <typename T> template <typename T>
using TUnwrapRefDecay = typename NAMESPACE_PRIVATE::TUnwrapRefDecayImpl<T>::Type; using TUnwrapRefDecay = typename NAMESPACE_PRIVATE::TUnwrapRefDecayImpl<T>::Type;
NAMESPACE_PRIVATE_BEGIN
template <typename T, typename U>
concept CTOptionalRefAllowUnwrappable =
!(CConstructibleFrom<U, TOptional<T>& >
|| CConstructibleFrom<U, const TOptional<T>& >
|| CConstructibleFrom<U, TOptional<T>&&>
|| CConstructibleFrom<U, const TOptional<T>&&>
|| CConvertibleTo< TOptional<T>&, U>
|| CConvertibleTo<const TOptional<T>&, U>
|| CConvertibleTo< TOptional<T>&&, U>
|| CConvertibleTo<const TOptional<T>&&, U>
|| CAssignableFrom<U&, TOptional<T>& >
|| CAssignableFrom<U&, const TOptional<T>& >
|| CAssignableFrom<U&, TOptional<T>&&>
|| CAssignableFrom<U&, const TOptional<T>&&>);
NAMESPACE_PRIVATE_END
template <typename ReferencedType> template <typename ReferencedType>
class TOptional<TReferenceWrapper<ReferencedType>> class TOptional<TReferenceWrapper<ReferencedType>>
{ {
@ -129,22 +148,6 @@ private:
using OptionalType = TReferenceWrapper<ReferencedType>; using OptionalType = TReferenceWrapper<ReferencedType>;
template <typename T>
struct TAllowUnwrapping : TBoolConstant < !(
CConstructibleFrom<OptionalType, TOptional<T>& >
|| CConstructibleFrom<OptionalType, const TOptional<T>& >
|| CConstructibleFrom<OptionalType, TOptional<T>&&>
|| CConstructibleFrom<OptionalType, const TOptional<T>&&>
|| CConvertibleTo< TOptional<T>&, OptionalType>
|| CConvertibleTo<const TOptional<T>&, OptionalType>
|| CConvertibleTo< TOptional<T>&&, OptionalType>
|| CConvertibleTo<const TOptional<T>&&, OptionalType>
|| CAssignableFrom<OptionalType&, TOptional<T>& >
|| CAssignableFrom<OptionalType&, const TOptional<T>& >
|| CAssignableFrom<OptionalType&, TOptional<T>&&>
|| CAssignableFrom<OptionalType&, const TOptional<T>&&>
)> { };
public: public:
using ValueType = OptionalType; using ValueType = OptionalType;
@ -167,7 +170,7 @@ public:
FORCEINLINE TOptional(const TOptional& InValue) = default; FORCEINLINE TOptional(const TOptional& InValue) = default;
FORCEINLINE TOptional(TOptional&& InValue) = default; FORCEINLINE TOptional(TOptional&& InValue) = default;
template <typename T = OptionalType> requires (CConstructibleFrom<OptionalType, const T&> && TAllowUnwrapping<T>::Value) template <typename T = OptionalType> requires (CConstructibleFrom<OptionalType, const T&> && NAMESPACE_PRIVATE::CTOptionalRefAllowUnwrappable<T, OptionalType>)
FORCEINLINE constexpr explicit (!CConvertibleTo<const T&, OptionalType>) TOptional(const TOptional<T>& InValue) FORCEINLINE constexpr explicit (!CConvertibleTo<const T&, OptionalType>) TOptional(const TOptional<T>& InValue)
: Reference(InValue.Reference) : Reference(InValue.Reference)
{ } { }
@ -178,7 +181,7 @@ public:
FORCEINLINE TOptional& operator=(TOptional&& InValue) = default; FORCEINLINE TOptional& operator=(TOptional&& InValue) = default;
template <typename T = OptionalType> requires (CConstructibleFrom<OptionalType, const T&> template <typename T = OptionalType> requires (CConstructibleFrom<OptionalType, const T&>
&& CAssignableFrom<OptionalType&, const T&> && TAllowUnwrapping<T>::Value) && CAssignableFrom<OptionalType&, const T&> && NAMESPACE_PRIVATE::CTOptionalRefAllowUnwrappable<T, OptionalType>)
FORCEINLINE constexpr TOptional& operator=(const TOptional<T>& InValue) FORCEINLINE constexpr TOptional& operator=(const TOptional<T>& InValue)
{ {
Reference = InValue.Reference; Reference = InValue.Reference;