mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 11:07:45 +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>
|
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 {} };
|
Variant<NewTs...> instance { Variant<NewTs...>::invalid_index, Detail::VariantConstructTag {} };
|
||||||
visit([&](auto& value) {
|
visit([&](auto& value) {
|
||||||
if constexpr (Variant<NewTs...>::template can_contain<RemoveCVReference<decltype(value)>>())
|
if constexpr (Variant<NewTs...>::template can_contain<RemoveCVReference<decltype(value)>>())
|
||||||
|
@ -416,10 +419,14 @@ public:
|
||||||
VERIFY(instance.m_index != instance.invalid_index);
|
VERIFY(instance.m_index != instance.invalid_index);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename... NewTs>
|
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 {} };
|
Variant<NewTs...> instance { Variant<NewTs...>::invalid_index, Detail::VariantConstructTag {} };
|
||||||
visit([&](auto const& value) {
|
visit([&](auto const& value) {
|
||||||
if constexpr (Variant<NewTs...>::template can_contain<RemoveCVReference<decltype(value)>>())
|
if constexpr (Variant<NewTs...>::template can_contain<RemoveCVReference<decltype(value)>>())
|
||||||
|
@ -428,8 +435,21 @@ public:
|
||||||
VERIFY(instance.m_index != instance.invalid_index);
|
VERIFY(instance.m_index != instance.invalid_index);
|
||||||
return instance;
|
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...>;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue