aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/string/format-inl.h
diff options
context:
space:
mode:
authorarkady-e1ppa <arkady-e1ppa@yandex-team.com>2024-08-07 13:31:32 +0300
committerarkady-e1ppa <arkady-e1ppa@yandex-team.com>2024-08-07 14:35:26 +0300
commitb92a4e77b0ee24fc7ae9d4488d97999ac39f48e3 (patch)
tree5bb3e970bb249ea0f0a42f58a65c5a5d6708e8a4 /library/cpp/yt/string/format-inl.h
parent933bb8d7a12d3881898904226e8884e8695275ef (diff)
downloadydb-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.h87
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