aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/misc/variant.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/yt/misc/variant.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/yt/misc/variant.h')
-rw-r--r--library/cpp/yt/misc/variant.h76
1 files changed, 76 insertions, 0 deletions
diff --git a/library/cpp/yt/misc/variant.h b/library/cpp/yt/misc/variant.h
new file mode 100644
index 00000000000..27c0a2bc086
--- /dev/null
+++ b/library/cpp/yt/misc/variant.h
@@ -0,0 +1,76 @@
+#pragma once
+
+#include <variant>
+
+namespace NYT {
+
+////////////////////////////////////////////////////////////////////////////////
+
+namespace NDetail {
+
+template <class T, class... Ts>
+struct TIndexOf;
+
+} // namespace NDetail
+
+template <class T, class V>
+struct TVariantIndex;
+
+template <class T, class... Ts>
+struct TVariantIndex<T, std::variant<Ts...>>
+ : std::integral_constant<size_t, NDetail::TIndexOf<T, Ts...>::Value>
+{ };
+
+template <class T, class V>
+constexpr size_t VariantIndexV = TVariantIndex<T, V>::value;
+
+////////////////////////////////////////////////////////////////////////////////
+
+class TStringBuilderBase;
+
+template <class... Ts>
+void FormatValue(TStringBuilderBase* builder, const std::variant<Ts...>& variant, TStringBuf spec);
+
+template <class... Ts>
+TString ToString(const std::variant<Ts...>& variant);
+
+////////////////////////////////////////////////////////////////////////////////
+
+//! A concise way of creating a functor with an overloaded operator().
+/*!
+ * Very useful for std::visit-ing variants. For example:
+ *
+ * std::visit(TOverloaded{
+ * [] (int i) { printf("The variant holds an int: %d!", i); },
+ * [] (const std::string& s) { printf("The variant holds a string: '%s'!", s); }
+ * }, variantVariable);
+ */
+template<class... Ts> struct TOverloaded : Ts... { using Ts::operator()...; };
+template<class... Ts> TOverloaded(Ts...) -> TOverloaded<Ts...>;
+
+////////////////////////////////////////////////////////////////////////////////
+
+//! An alternative to std::visit that takes its variant argument first.
+/*!
+ * This deprives it of being able to visit a Cartesian product of variants but
+ * in exchange allows to receive multiple visitor functors. All of operator()s
+ * these functors have are used to visit the variant after a single unified
+ * overload resolution. For example:
+ *
+ * Visit(variantVariable,
+ * [] (int i) { printf("The variant holds an int: %d!", i); },
+ * [] (const std::string& s) { printf("The variant holds a string: '%s'!", s); });
+ */
+template <class T, class... U>
+auto Visit(T&& variant, U&&... visitorOverloads)
+{
+ return std::visit(TOverloaded{std::forward<U>(visitorOverloads)...}, std::forward<T>(variant));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT
+
+#define VARIANT_INL_H_
+#include "variant-inl.h"
+#undef VARIANT_INL_H_