AK: Allow derived types to create base badges
Derived classes can now mint their own badge and pass it to APIs that accept a badge for an authorized base class.
This commit is contained in:
parent
ad3d65b834
commit
071b4f7062
2 changed files with 121 additions and 2 deletions
49
AK/Badge.h
49
AK/Badge.h
|
|
@ -8,9 +8,18 @@
|
|||
|
||||
#include <AK/Noncopyable.h>
|
||||
#include <AK/Platform.h>
|
||||
#include <AK/StdLibExtraDetails.h>
|
||||
|
||||
namespace AK {
|
||||
|
||||
namespace Detail {
|
||||
|
||||
template<typename AuthorizedType, typename BadgeType>
|
||||
inline constexpr bool IsBadgeType = IsSame<AuthorizedType, BadgeType>
|
||||
|| IsBaseOf<AuthorizedType, BadgeType>;
|
||||
|
||||
}
|
||||
|
||||
template<typename...>
|
||||
class Badge;
|
||||
|
||||
|
|
@ -22,6 +31,14 @@ class Badge<T> {
|
|||
public:
|
||||
using Type = T;
|
||||
|
||||
// Friendship is not inherited, so derived classes mint Badge<Derived> and
|
||||
// convert it to Badge<Base>.
|
||||
template<typename U>
|
||||
requires(IsBaseOf<T, U> && !IsSame<T, U>)
|
||||
constexpr Badge(Badge<U> const&)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
friend T;
|
||||
constexpr Badge() = default;
|
||||
|
|
@ -34,6 +51,13 @@ class Badge<T, U> {
|
|||
AK_MAKE_NONCOPYABLE(Badge);
|
||||
AK_MAKE_NONMOVABLE(Badge);
|
||||
|
||||
public:
|
||||
template<typename V>
|
||||
requires(Detail::IsBadgeType<T, V> || Detail::IsBadgeType<U, V>)
|
||||
constexpr Badge(Badge<V> const&)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
friend T;
|
||||
friend U;
|
||||
|
|
@ -45,6 +69,14 @@ class Badge<T, U, V> {
|
|||
AK_MAKE_NONCOPYABLE(Badge);
|
||||
AK_MAKE_NONMOVABLE(Badge);
|
||||
|
||||
public:
|
||||
template<typename W>
|
||||
requires(Detail::IsBadgeType<T, W> || Detail::IsBadgeType<U, W>
|
||||
|| Detail::IsBadgeType<V, W>)
|
||||
constexpr Badge(Badge<W> const&)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
friend T;
|
||||
friend U;
|
||||
|
|
@ -57,6 +89,14 @@ class Badge<T, U, V, W> {
|
|||
AK_MAKE_NONCOPYABLE(Badge);
|
||||
AK_MAKE_NONMOVABLE(Badge);
|
||||
|
||||
public:
|
||||
template<typename X>
|
||||
requires(Detail::IsBadgeType<T, X> || Detail::IsBadgeType<U, X>
|
||||
|| Detail::IsBadgeType<V, X> || Detail::IsBadgeType<W, X>)
|
||||
constexpr Badge(Badge<X> const&)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
friend T;
|
||||
friend U;
|
||||
|
|
@ -70,6 +110,15 @@ class Badge<T, U, V, W, X> {
|
|||
AK_MAKE_NONCOPYABLE(Badge);
|
||||
AK_MAKE_NONMOVABLE(Badge);
|
||||
|
||||
public:
|
||||
template<typename Y>
|
||||
requires(Detail::IsBadgeType<T, Y> || Detail::IsBadgeType<U, Y>
|
||||
|| Detail::IsBadgeType<V, Y> || Detail::IsBadgeType<W, Y>
|
||||
|| Detail::IsBadgeType<X, Y>)
|
||||
constexpr Badge(Badge<Y> const&)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
friend T;
|
||||
friend U;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,16 @@ struct MultipleBadgeUserE {
|
|||
struct UnrelatedBadgeUser {
|
||||
};
|
||||
|
||||
struct BaseBadgeUser {
|
||||
static void call_base_badge();
|
||||
static void call_multi_base_badge();
|
||||
};
|
||||
|
||||
struct DerivedBadgeUser : BaseBadgeUser {
|
||||
static void call_base_badge();
|
||||
static void call_multi_base_badge();
|
||||
};
|
||||
|
||||
static void accepts_two_argument_badge(Badge<MultipleBadgeUserA, MultipleBadgeUserB>)
|
||||
{
|
||||
}
|
||||
|
|
@ -52,6 +62,14 @@ static void accepts_five_argument_badge(Badge<MultipleBadgeUserA, MultipleBadgeU
|
|||
{
|
||||
}
|
||||
|
||||
static void accepts_base_badge(Badge<BaseBadgeUser>)
|
||||
{
|
||||
}
|
||||
|
||||
static void accepts_multi_base_badge(Badge<BaseBadgeUser, MultipleBadgeUserB>)
|
||||
{
|
||||
}
|
||||
|
||||
void MultipleBadgeUserA::call_two_argument_badge()
|
||||
{
|
||||
accepts_two_argument_badge({});
|
||||
|
|
@ -92,6 +110,26 @@ void MultipleBadgeUserE::call_five_argument_badge()
|
|||
accepts_five_argument_badge({});
|
||||
}
|
||||
|
||||
void BaseBadgeUser::call_base_badge()
|
||||
{
|
||||
accepts_base_badge({});
|
||||
}
|
||||
|
||||
void BaseBadgeUser::call_multi_base_badge()
|
||||
{
|
||||
accepts_multi_base_badge({});
|
||||
}
|
||||
|
||||
void DerivedBadgeUser::call_base_badge()
|
||||
{
|
||||
accepts_base_badge(Badge<DerivedBadgeUser> {});
|
||||
}
|
||||
|
||||
void DerivedBadgeUser::call_multi_base_badge()
|
||||
{
|
||||
accepts_multi_base_badge(Badge<DerivedBadgeUser> {});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE(should_provide_underlying_type)
|
||||
|
|
@ -104,11 +142,13 @@ TEST_CASE(should_allow_multiple_underlying_types)
|
|||
static_assert(!IsConstructible<Badge<MultipleBadgeUserA, MultipleBadgeUserB>>);
|
||||
static_assert(!IsConstructible<Badge<MultipleBadgeUserA, MultipleBadgeUserB, MultipleBadgeUserC>>);
|
||||
static_assert(!IsConstructible<Badge<MultipleBadgeUserA, MultipleBadgeUserB, MultipleBadgeUserC, MultipleBadgeUserD>>);
|
||||
static_assert(!IsConstructible<Badge<MultipleBadgeUserA, MultipleBadgeUserB>, Badge<MultipleBadgeUserA>>);
|
||||
static_assert(!IsConstructible<Badge<MultipleBadgeUserA, MultipleBadgeUserB, MultipleBadgeUserC, MultipleBadgeUserD, MultipleBadgeUserE>>);
|
||||
static_assert(!IsConstructible<
|
||||
static_assert(IsConstructible<
|
||||
Badge<MultipleBadgeUserA, MultipleBadgeUserB, MultipleBadgeUserC, MultipleBadgeUserD, MultipleBadgeUserE>,
|
||||
Badge<MultipleBadgeUserA> const&>);
|
||||
static_assert(IsConstructible<
|
||||
Badge<MultipleBadgeUserA, MultipleBadgeUserB>,
|
||||
Badge<MultipleBadgeUserA> const&>);
|
||||
static_assert(!IsConstructible<Badge<MultipleBadgeUserA, MultipleBadgeUserB>, Badge<UnrelatedBadgeUser>>);
|
||||
|
||||
MultipleBadgeUserA::call_two_argument_badge();
|
||||
|
|
@ -120,3 +160,33 @@ TEST_CASE(should_allow_multiple_underlying_types)
|
|||
MultipleBadgeUserD::call_four_argument_badge();
|
||||
MultipleBadgeUserE::call_five_argument_badge();
|
||||
}
|
||||
|
||||
TEST_CASE(should_allow_derived_types_to_create_base_badges)
|
||||
{
|
||||
static_assert(IsConstructible<
|
||||
Badge<BaseBadgeUser>,
|
||||
Badge<DerivedBadgeUser> const&>);
|
||||
static_assert(IsConstructible<
|
||||
Badge<BaseBadgeUser, MultipleBadgeUserB>,
|
||||
Badge<BaseBadgeUser> const&>);
|
||||
static_assert(IsConstructible<
|
||||
Badge<BaseBadgeUser, MultipleBadgeUserB>,
|
||||
Badge<DerivedBadgeUser> const&>);
|
||||
static_assert(IsConstructible<
|
||||
Badge<BaseBadgeUser, MultipleBadgeUserB, MultipleBadgeUserC, MultipleBadgeUserD, MultipleBadgeUserE>,
|
||||
Badge<DerivedBadgeUser> const&>);
|
||||
static_assert(!IsConstructible<
|
||||
Badge<DerivedBadgeUser>,
|
||||
Badge<BaseBadgeUser> const&>);
|
||||
static_assert(!IsConstructible<
|
||||
Badge<BaseBadgeUser>,
|
||||
Badge<BaseBadgeUser, MultipleBadgeUserB> const&>);
|
||||
static_assert(!IsConstructible<
|
||||
Badge<BaseBadgeUser>,
|
||||
Badge<UnrelatedBadgeUser> const&>);
|
||||
|
||||
BaseBadgeUser::call_base_badge();
|
||||
BaseBadgeUser::call_multi_base_badge();
|
||||
DerivedBadgeUser::call_base_badge();
|
||||
DerivedBadgeUser::call_multi_base_badge();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue