diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/yt/misc/variant.h | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/yt/misc/variant.h')
-rw-r--r-- | library/cpp/yt/misc/variant.h | 76 |
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_ |