diff options
author | arkady-e1ppa <arkady-e1ppa@yandex-team.com> | 2024-08-07 13:31:32 +0300 |
---|---|---|
committer | arkady-e1ppa <arkady-e1ppa@yandex-team.com> | 2024-08-07 14:35:26 +0300 |
commit | b92a4e77b0ee24fc7ae9d4488d97999ac39f48e3 (patch) | |
tree | 5bb3e970bb249ea0f0a42f58a65c5a5d6708e8a4 /library/cpp/yt/string/format-inl.h | |
parent | 933bb8d7a12d3881898904226e8884e8695275ef (diff) | |
download | ydb-b92a4e77b0ee24fc7ae9d4488d97999ac39f48e3.tar.gz |
YT-22473: Enable for-each formatting in known ranges
5a3405e64b730f0056e381af07658d6c2edcb92b
Diffstat (limited to 'library/cpp/yt/string/format-inl.h')
-rw-r--r-- | library/cpp/yt/string/format-inl.h | 87 |
1 files changed, 73 insertions, 14 deletions
diff --git a/library/cpp/yt/string/format-inl.h b/library/cpp/yt/string/format-inl.h index 4eaa70bef2..67c8affa6e 100644 --- a/library/cpp/yt/string/format-inl.h +++ b/library/cpp/yt/string/format-inl.h @@ -222,24 +222,67 @@ void FormatPointerValue( // so that someone doesn't accidentally implement the // "SimpleRange" concept and have a non-trivial // formatting procedure at the same time. +// Sadly, clang is bugged and thus we must do implementation by hand +// if we want to use this concept in class specializations. template <class R> -concept CKnownRange = - requires (R r) { [] <class... Ts> (std::vector<Ts...>) { } (r); } || - requires (R r) { [] <class T, size_t E> (std::span<T, E>) { } (r); } || - requires (R r) { [] <class T, size_t N> (TCompactVector<T, N>) { } (r); } || - requires (R r) { [] <class... Ts> (std::set<Ts...>) { } (r); } || - requires (R r) { [] <class... Ts> (THashSet<Ts...>) { } (r); } || - requires (R r) { [] <class... Ts> (THashMultiSet<Ts...>) { } (r); }; +constexpr bool CKnownRange = false; + +template <class T> + requires requires (T* t) { [] <class... Ts> (std::vector<Ts...>*) {} (t); } +constexpr bool CKnownRange<T> = true; +template <class T, size_t E> +constexpr bool CKnownRange<std::span<T, E>> = true; +template <class T, size_t N> +constexpr bool CKnownRange<std::array<T, N>> = true; +template <class T, size_t N> +constexpr bool CKnownRange<TCompactVector<T, N>> = true; +template <class T> + requires requires (T* t) { [] <class... Ts> (std::set<Ts...>*) {} (t); } +constexpr bool CKnownRange<T> = true; +template <class T> + requires requires (T* t) { [] <class... Ts> (std::multiset<Ts...>*) {} (t); } +constexpr bool CKnownRange<T> = true; +template <class... Ts> +constexpr bool CKnownRange<THashSet<Ts...>> = true; +template <class... Ts> +constexpr bool CKnownRange<THashMultiSet<Ts...>> = true; //////////////////////////////////////////////////////////////////////////////// template <class R> -concept CKnownKVRange = - requires (R r) { [] <class... Ts> (std::map<Ts...>) { } (r); } || - requires (R r) { [] <class... Ts> (std::multimap<Ts...>) { } (r); } || - requires (R r) { [] <class... Ts> (THashMap<Ts...>) { } (r); } || - requires (R r) { [] <class... Ts> (THashMultiMap<Ts...>) { } (r); }; +constexpr bool CKnownKVRange = false; + +template <class T> + requires requires (T* t) { [] <class... Ts> (std::map<Ts...>*) {} (t); } +constexpr bool CKnownKVRange<T> = true; +template <class T> + requires requires (T* t) { [] <class... Ts> (std::multimap<Ts...>*) {} (t); } +constexpr bool CKnownKVRange<T> = true; +template <class... Ts> +constexpr bool CKnownKVRange<THashMap<Ts...>> = true; +template <class... Ts> +constexpr bool CKnownKVRange<THashMultiMap<Ts...>> = true; + +// TODO(arkady-e1ppa): Uncomment me when +// https://github.com/llvm/llvm-project/issues/58534 is shipped. +// template <class R> +// concept CKnownRange = +// requires (R r) { [] <class... Ts> (std::vector<Ts...>) { } (r); } || +// requires (R r) { [] <class T, size_t E> (std::span<T, E>) { } (r); } || +// requires (R r) { [] <class T, size_t N> (TCompactVector<T, N>) { } (r); } || +// requires (R r) { [] <class... Ts> (std::set<Ts...>) { } (r); } || +// requires (R r) { [] <class... Ts> (THashSet<Ts...>) { } (r); } || +// requires (R r) { [] <class... Ts> (THashMultiSet<Ts...>) { } (r); }; + +// //////////////////////////////////////////////////////////////////////////////// + +// template <class R> +// concept CKnownKVRange = +// requires (R r) { [] <class... Ts> (std::map<Ts...>) { } (r); } || +// requires (R r) { [] <class... Ts> (std::multimap<Ts...>) { } (r); } || +// requires (R r) { [] <class... Ts> (THashMap<Ts...>) { } (r); } || +// requires (R r) { [] <class... Ts> (THashMultiMap<Ts...>) { } (r); }; } // namespace NDetail @@ -300,6 +343,22 @@ concept CFormattableKVRange = CFormattable<typename R::key_type> && CFormattable<typename R::value_type>; + +//////////////////////////////////////////////////////////////////////////////// + +// Specializations of TFormatArg for ranges +template <class R> + requires CFormattableRange<std::remove_cvref_t<R>> +struct TFormatArg<R> + : public TFormatArgBase +{ + using TUnderlying = typename std::remove_cvref_t<R>::value_type; + + static constexpr auto ConversionSpecifiers = TFormatArg<TUnderlying>::ConversionSpecifiers; + + static constexpr auto FlagSpecifiers = TFormatArg<TUnderlying>::FlagSpecifiers; +}; + //////////////////////////////////////////////////////////////////////////////// template <class TRange, class TFormatter> @@ -740,9 +799,9 @@ void FormatValue(TStringBuilderBase* builder, const TEnumIndexedArray<E, T>& col // One-valued ranges template <CFormattableRange TRange> -void FormatValue(TStringBuilderBase* builder, const TRange& collection, TStringBuf /*spec*/) +void FormatValue(TStringBuilderBase* builder, const TRange& collection, TStringBuf spec) { - NYT::FormatRange(builder, collection, TDefaultFormatter()); + NYT::FormatRange(builder, collection, TSpecBoundFormatter(spec)); } // Two-valued ranges |