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 /util/generic/overloaded.h | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/generic/overloaded.h')
-rw-r--r-- | util/generic/overloaded.h | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/util/generic/overloaded.h b/util/generic/overloaded.h new file mode 100644 index 0000000000..96a97e44bc --- /dev/null +++ b/util/generic/overloaded.h @@ -0,0 +1,56 @@ +#pragma once + +/** + * Construct an ad-hoc object with an overloaded `operator()`. + * + * Typically used with lambdas to construct type-matching visitors for e.g. std::variant: + * ``` + * std::variant<int, void*, TString> var; + * Visit(TOverloaded{ + * [](int val) { Cerr << "int: " << val; }, + * [](void* val) { Cerr << "ptr: " << val; }, + * [](const TString& val) { Cerr << "str: " << val; }, + * }, var); + * ``` + * + * *** IMPORTANT NOTE (IMPLICIT ARGUMENT CONVERSIONS) *** + * + * Since the resulting objects use regular overloaded method resolution rules, + * methods may be called by inexact matches (causing implicit casts), hence this + * implementation does not guarantee exhaustiveness of cases. + * + * For example, the following code will compile and run by casting all values to + * double: + * ``` + * std::variant<int, double, char> var; + * Visit(TOverloaded{ + * [](double val) { Cerr << "dbl: " << val; }, + * }, var); + * ``` + * + * If cases may be ambigous or specific type-matching logic is required, + * a verbose `if constexpr`-based version would be preferred: + * ``` + * std::variant<int, double, char> var; + * Visit([](auto&& val) { + * using T = std::decay_t<decltype(val)>; + * if constexpr (std::is_same_v<T, int>) { + * Cerr << "int: " << val; + * } else if constexpr (std::is_same_v<T, double>) { + * Cerr << "dbl: " << val; + * } else if constexpr (std::is_same_v<T, char>) { + * Cerr << "chr: " << val; + * } else { + * static_assert(TDependentFalse<T>, "unexpected type"); + * } + * }, var); + * ``` + */ + +template <class... Fs> +struct TOverloaded: Fs... { + using Fs::operator()...; +}; + +template <class... Fs> +TOverloaded(Fs...) -> TOverloaded<Fs...>; |