diff options
author | Ali Mohammad Pur <ali.mpfard@gmail.com> | 2022-11-10 12:42:19 +0330 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2022-11-10 16:02:42 +0330 |
commit | 40b07901ac3cdc4e8942bff62f4784370543003b (patch) | |
tree | 1fbc8773c48520df6451c829723dba7118b9f3ea /AK | |
parent | 4a9218451dbf6bd5b58addd37f7e334669882ece (diff) | |
download | serenity-40b07901ac3cdc4e8942bff62f4784370543003b.zip |
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.
Diffstat (limited to 'AK')
-rw-r--r-- | AK/Variant.h | 54 |
1 files changed, 37 insertions, 17 deletions
diff --git a/AK/Variant.h b/AK/Variant.h index 8962b7ee0a..eb6500bc44 100644 --- a/AK/Variant.h +++ b/AK/Variant.h @@ -406,30 +406,50 @@ 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)>>()) + instance.set(move(value), Detail::VariantNoClearTag {}); + }); + VERIFY(instance.m_index != instance.invalid_index); + return instance; + } + } + + template<typename... NewTs> + 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)>>()) + 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...>>) && { - 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; + return move(*this).template downcast<NewTs...>(); } template<typename... NewTs> - Variant<NewTs...> downcast() const& + Variant<NewTs...> downcast_variant(TypeWrapper<Variant<NewTs...>>) 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; + return (*this).template downcast<NewTs...>(); } -private: 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...>; |