diff --git a/library/include/larra/serialization.hpp b/library/include/larra/serialization.hpp index 60b2f58..31b127a 100644 --- a/library/include/larra/serialization.hpp +++ b/library/include/larra/serialization.hpp @@ -138,19 +138,32 @@ struct Serialization> : SerializationBase<> { static constexpr auto StartCheck(xmlpp::Element* element) { return true; } - [[nodiscard]] static constexpr auto TryParse(xmlpp::Element* element) -> std::optional> { - return utempl::FirstOf(utempl::Tuple{[&] -> std::optional { - if(Serialization::StartCheck(element)) { - return Serialization::TryParse(element); - } else { - SPDLOG_DEBUG("StartCheck failed for type {}", nameof::nameof_type()); - return std::nullopt; - } - }...}, - std::optional>{}); + + private: + template + static constexpr auto FunctionForType(xmlpp::Element* element) { + return [=] -> std::optional { + if(Serialization::StartCheck(element)) { + return Serialization::TryParse(element); + } else { + SPDLOG_DEBUG("StartCheck failed for type {}", nameof::nameof_type()); + return std::nullopt; + } + }; } - [[nodiscard]] static constexpr auto Parse(xmlpp::Element* element) -> std::variant { - return Serialization::TryParse(element).value(); + + public: + [[nodiscard]] static constexpr auto TryParse(xmlpp::Element* element) -> std::optional> { + return utempl::FirstOf(utempl::Tuple{FunctionForType(element)...}, std::optional>{}); + } + [[nodiscard]] static constexpr auto Parse(xmlpp::Element* element) { + return [&](utempl::TypeList) { + // operator* is safe because in or_else Parse returns Ts...[sizeof...(Ts) - 1] (not optional) + return *utempl::FirstOf(utempl::Tuple{FunctionForType(element)...}, std::optional>{}) + .or_else([&] -> std::optional> { + return Serialization(utempl::kTypeList))>::Parse(element); + }); + }(utempl::TakeFrom(utempl::kTypeList)); } static constexpr auto Serialize(xmlpp::Element* element, const std::variant& object) -> void { std::visit(