#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include #include #include "llvm/Support/YAMLTraits.h" /// Trait to provide name of the tuple-like class and its fields template struct TupleLikeTraits { enum class Fields {}; }; template concept HasTupleLikeTraits = requires { typename TupleLikeTraits::tuple; typename TupleLikeTraits::Fields; { TupleLikeTraits::Name }; { TupleLikeTraits::FieldsName }; }; // // Implementation of MappingTraits for TupleLikeTraits implementors // /// Tuple-like can implement llvm::yaml::MappingTraits inheriting this class template::Fields... Optionals> struct TupleLikeMappingTraits { using Fields = typename TupleLikeTraits::Fields; template static constexpr bool isOptional() { constexpr size_t Count = sizeof...(Optionals); constexpr std::array OptionalsArray{ Optionals... }; if constexpr (I < Count) { return (OptionalsArray[I] == Index) || isOptional(); } else { return false; } } // Recursive step template static void mapping(llvm::yaml::IO &IO, T &Obj) { if constexpr (I < std::tuple_size_v) { auto Name = TupleLikeTraits::FieldsName[I]; constexpr Fields Field = static_cast(I); using tuple_element = std::tuple_element_t; auto &Element = get(Obj); if constexpr (isOptional()) { IO.mapOptional(Name, Element, tuple_element{}); } else { IO.mapRequired(Name, Element); } // Recur mapping(IO, Obj); } } }; template struct std::tuple_element { using type = std::tuple_element_t::tuple>; }; template using TupleLikeTraitsTuple = typename TupleLikeTraits::tuple; template struct std::tuple_size : std::integral_constant>> { };