1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-09 09:34:57 +09: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:
Ali Mohammad Pur 2022-11-10 12:42:19 +03:30 committed by Ali Mohammad Pur
parent 4a9218451d
commit 40b07901ac
Notes: sideshowbarker 2024-07-17 04:38:07 +09:00
2 changed files with 43 additions and 16 deletions

View file

@ -406,30 +406,50 @@ public:
} }
template<typename... NewTs> template<typename... NewTs>
Variant<NewTs...> downcast() && decltype(auto) downcast() &&
{ {
Variant<NewTs...> instance { Variant<NewTs...>::invalid_index, Detail::VariantConstructTag {} }; if constexpr (sizeof...(NewTs) == 1 && (IsSpecializationOf<NewTs, Variant> && ...)) {
visit([&](auto& value) { return move(*this).template downcast_variant<NewTs...>();
if constexpr (Variant<NewTs...>::template can_contain<RemoveCVReference<decltype(value)>>()) } else {
instance.set(move(value), Detail::VariantNoClearTag {}); Variant<NewTs...> instance { Variant<NewTs...>::invalid_index, Detail::VariantConstructTag {} };
}); visit([&](auto& value) {
VERIFY(instance.m_index != instance.invalid_index); if constexpr (Variant<NewTs...>::template can_contain<RemoveCVReference<decltype(value)>>())
return instance; instance.set(move(value), Detail::VariantNoClearTag {});
});
VERIFY(instance.m_index != instance.invalid_index);
return instance;
}
} }
template<typename... NewTs> template<typename... NewTs>
Variant<NewTs...> downcast() const& decltype(auto) downcast() const&
{ {
Variant<NewTs...> instance { Variant<NewTs...>::invalid_index, Detail::VariantConstructTag {} }; if constexpr (sizeof...(NewTs) == 1 && (IsSpecializationOf<NewTs, Variant> && ...)) {
visit([&](auto const& value) { return (*this).template downcast_variant(TypeWrapper<NewTs...> {});
if constexpr (Variant<NewTs...>::template can_contain<RemoveCVReference<decltype(value)>>()) } else {
instance.set(value, Detail::VariantNoClearTag {}); Variant<NewTs...> instance { Variant<NewTs...>::invalid_index, Detail::VariantConstructTag {} };
}); visit([&](auto const& value) {
VERIFY(instance.m_index != instance.invalid_index); if constexpr (Variant<NewTs...>::template can_contain<RemoveCVReference<decltype(value)>>())
return instance; instance.set(value, Detail::VariantNoClearTag {});
});
VERIFY(instance.m_index != instance.invalid_index);
return instance;
}
} }
private: 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_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(); 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...>; using Helper = Detail::Variant<IndexType, 0, Ts...>;

View file

@ -125,6 +125,13 @@ TEST_CASE(verify_cast)
EXPECT(one_integer_to_rule_them_all.has<i8>()); EXPECT(one_integer_to_rule_them_all.has<i8>());
EXPECT_EQ(fake_integer.get<i8>(), 60); EXPECT_EQ(fake_integer.get<i8>(), 60);
EXPECT_EQ(one_integer_to_rule_them_all.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) TEST_CASE(moved_from_state)