mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-04 05:20:30 +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
Notes:
sideshowbarker
2024-07-17 04:38:07 +09:00
Author: https://github.com/alimpfard Commit: https://github.com/SerenityOS/serenity/commit/40b07901ac Pull-request: https://github.com/SerenityOS/serenity/pull/16002 Reviewed-by: https://github.com/linusg ✅
2 changed files with 43 additions and 16 deletions
52
AK/Variant.h
52
AK/Variant.h
|
@ -406,30 +406,50 @@ public:
|
|||
}
|
||||
|
||||
template<typename... NewTs>
|
||||
Variant<NewTs...> downcast() &&
|
||||
decltype(auto) downcast() &&
|
||||
{
|
||||
Variant<NewTs...> instance { Variant<NewTs...>::invalid_index, Detail::VariantConstructTag {} };
|
||||
visit([&](auto& value) {
|
||||
if constexpr (Variant<NewTs...>::template can_contain<RemoveCVReference<decltype(value)>>())
|
||||
instance.set(move(value), Detail::VariantNoClearTag {});
|
||||
});
|
||||
VERIFY(instance.m_index != instance.invalid_index);
|
||||
return instance;
|
||||
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)>>())
|
||||
instance.set(move(value), Detail::VariantNoClearTag {});
|
||||
});
|
||||
VERIFY(instance.m_index != instance.invalid_index);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... NewTs>
|
||||
Variant<NewTs...> downcast() const&
|
||||
decltype(auto) downcast() const&
|
||||
{
|
||||
Variant<NewTs...> instance { Variant<NewTs...>::invalid_index, Detail::VariantConstructTag {} };
|
||||
visit([&](auto const& value) {
|
||||
if constexpr (Variant<NewTs...>::template can_contain<RemoveCVReference<decltype(value)>>())
|
||||
instance.set(value, Detail::VariantNoClearTag {});
|
||||
});
|
||||
VERIFY(instance.m_index != instance.invalid_index);
|
||||
return instance;
|
||||
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)>>())
|
||||
instance.set(value, Detail::VariantNoClearTag {});
|
||||
});
|
||||
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…
Reference in a new issue