mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 09:37:34 +00:00
AK: Allow Variant::downcast<OtherVariantType>()
We usually give type aliases to variants, so their variant types are not always available, so make it possible to downcast to another variant type.
This commit is contained in:
parent
4a9218451d
commit
40b07901ac
2 changed files with 43 additions and 16 deletions
24
AK/Variant.h
24
AK/Variant.h
|
@ -406,8 +406,11 @@ public:
|
|||
}
|
||||
|
||||
template<typename... NewTs>
|
||||
Variant<NewTs...> downcast() &&
|
||||
decltype(auto) downcast() &&
|
||||
{
|
||||
if constexpr (sizeof...(NewTs) == 1 && (IsSpecializationOf<NewTs, Variant> && ...)) {
|
||||
return move(*this).template downcast_variant<NewTs...>();
|
||||
} else {
|
||||
Variant<NewTs...> instance { Variant<NewTs...>::invalid_index, Detail::VariantConstructTag {} };
|
||||
visit([&](auto& value) {
|
||||
if constexpr (Variant<NewTs...>::template can_contain<RemoveCVReference<decltype(value)>>())
|
||||
|
@ -416,10 +419,14 @@ public:
|
|||
VERIFY(instance.m_index != instance.invalid_index);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... NewTs>
|
||||
Variant<NewTs...> downcast() const&
|
||||
decltype(auto) downcast() const&
|
||||
{
|
||||
if constexpr (sizeof...(NewTs) == 1 && (IsSpecializationOf<NewTs, Variant> && ...)) {
|
||||
return (*this).template downcast_variant(TypeWrapper<NewTs...> {});
|
||||
} else {
|
||||
Variant<NewTs...> instance { Variant<NewTs...>::invalid_index, Detail::VariantConstructTag {} };
|
||||
visit([&](auto const& value) {
|
||||
if constexpr (Variant<NewTs...>::template can_contain<RemoveCVReference<decltype(value)>>())
|
||||
|
@ -428,8 +435,21 @@ public:
|
|||
VERIFY(instance.m_index != instance.invalid_index);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename... NewTs>
|
||||
Variant<NewTs...> downcast_variant(TypeWrapper<Variant<NewTs...>>) &&
|
||||
{
|
||||
return move(*this).template downcast<NewTs...>();
|
||||
}
|
||||
|
||||
template<typename... NewTs>
|
||||
Variant<NewTs...> downcast_variant(TypeWrapper<Variant<NewTs...>>) const&
|
||||
{
|
||||
return (*this).template downcast<NewTs...>();
|
||||
}
|
||||
|
||||
static constexpr auto data_size = Detail::integer_sequence_generate_array<size_t>(0, IntegerSequence<size_t, sizeof(Ts)...>()).max();
|
||||
static constexpr auto data_alignment = Detail::integer_sequence_generate_array<size_t>(0, IntegerSequence<size_t, alignof(Ts)...>()).max();
|
||||
using Helper = Detail::Variant<IndexType, 0, Ts...>;
|
||||
|
|
|
@ -125,6 +125,13 @@ TEST_CASE(verify_cast)
|
|||
EXPECT(one_integer_to_rule_them_all.has<i8>());
|
||||
EXPECT_EQ(fake_integer.get<i8>(), 60);
|
||||
EXPECT_EQ(one_integer_to_rule_them_all.get<i8>(), 60);
|
||||
|
||||
using SomeFancyType = Variant<i8, i16>;
|
||||
one_integer_to_rule_them_all = fake_integer.downcast<SomeFancyType>();
|
||||
EXPECT(fake_integer.has<i8>());
|
||||
EXPECT(one_integer_to_rule_them_all.has<i8>());
|
||||
EXPECT_EQ(fake_integer.get<i8>(), 60);
|
||||
EXPECT_EQ(one_integer_to_rule_them_all.get<i8>(), 60);
|
||||
}
|
||||
|
||||
TEST_CASE(moved_from_state)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue