#pragma once #include "public.h" #include "error_attribute.h" #include namespace NYT { //////////////////////////////////////////////////////////////////////////////// // Can be specialized to make your dictionary satisfy CMergeableDictionary. template struct TMergeDictionariesTraits { static auto MakeIterableView(const TDictionary& dict) requires false; }; //////////////////////////////////////////////////////////////////////////////// namespace NDetail { template struct TMergeableDictionaryImpl { // TL;DR: MakeIterableView returns something like std::span>. using TView = std::invoke_result_t::MakeIterableView), const T&>; using TIterator = std::ranges::iterator_t; using TValue = typename std::iterator_traits::value_type; static constexpr bool ValidSize = requires { { std::tuple_size::value } -> std::same_as; } && (std::tuple_size::value == 2); static constexpr bool CorrectTupleElements = requires { typename std::tuple_element<0, TValue>::type; std::same_as::type, TErrorAttribute::TKey>; typename std::tuple_element<1, TValue>::type; std::same_as::type, TErrorAttribute::TValue>; }; }; } // namespace NDetail //////////////////////////////////////////////////////////////////////////////// template concept CMergeableDictionary = requires (const T& dict) { TMergeDictionariesTraits::MakeIterableView(dict); } && NDetail::TMergeableDictionaryImpl::ValidSize && NDetail::TMergeableDictionaryImpl::CorrectTupleElements; //////////////////////////////////////////////////////////////////////////////// } // namespace NYT