Add void to Switch
This commit is contained in:
parent
eaddebf1e5
commit
e15d520cfa
2 changed files with 34 additions and 14 deletions
|
@ -20,4 +20,11 @@ auto main() -> int {
|
||||||
[] {
|
[] {
|
||||||
return 42;
|
return 42;
|
||||||
}) == 42);
|
}) == 42);
|
||||||
|
static_assert([] {
|
||||||
|
int response{};
|
||||||
|
utempl::Switch(utempl::Tuple{2, 1, 0}, utempl::Tuple{0, 1, 2}, 0, [&](int value) {
|
||||||
|
response = value + 1;
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
}() == 3);
|
||||||
};
|
};
|
||||||
|
|
|
@ -644,11 +644,14 @@ constexpr auto Enumerate(Tuple&& tuple) {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires requires { T{}; }
|
requires std::same_as<T, void> || requires { T{}; }
|
||||||
constexpr auto kDefaultCreator = [] {
|
constexpr auto kDefaultCreator = [] {
|
||||||
return T{};
|
return T{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
constexpr auto kDefaultCreator<void> = [] {};
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
template <typename Key, typename KeysTuple>
|
template <typename Key, typename KeysTuple>
|
||||||
|
@ -657,21 +660,30 @@ concept ComparableSwitchConcept = decltype(Unpack(std::declval<KeysTuple>(), []<
|
||||||
}))::kValue;
|
}))::kValue;
|
||||||
|
|
||||||
template <typename F, typename ValuesTuple, typename R>
|
template <typename F, typename ValuesTuple, typename R>
|
||||||
concept CallableSwitchConcept = decltype(Unpack(std::declval<ValuesTuple>(), []<typename... Ts>(Ts&&...) {
|
concept CallableSwitchConcept = std::same_as<R, void> || decltype(Unpack(std::declval<ValuesTuple>(), []<typename... Ts>(Ts&&...) {
|
||||||
return kWrapper<(std::convertible_to<std::invoke_result_t<F, Ts>, std::optional<R>> && ...)>;
|
return kWrapper<(std::convertible_to<std::invoke_result_t<F, Ts>, std::optional<R>> && ...)>;
|
||||||
}))::kValue;
|
}))::kValue;
|
||||||
|
|
||||||
} // namespace impl
|
} // namespace impl
|
||||||
|
|
||||||
template <std::move_constructible R,
|
template <typename R = void,
|
||||||
TupleLike KeysTuple,
|
TupleLike KeysTuple,
|
||||||
TupleLike ValuesTuple,
|
TupleLike ValuesTuple,
|
||||||
impl::ComparableSwitchConcept<KeysTuple> Key,
|
impl::ComparableSwitchConcept<KeysTuple> Key,
|
||||||
impl::CallableSwitchConcept<ValuesTuple, R> F,
|
impl::CallableSwitchConcept<ValuesTuple, R> F,
|
||||||
std::invocable Default = decltype(kDefaultCreator<R>)>
|
std::invocable Default = decltype(kDefaultCreator<R>)>
|
||||||
constexpr auto Switch(KeysTuple&& keysTuple, ValuesTuple&& valuesTuple, Key&& key, F&& f, Default&& def = {}) {
|
constexpr auto Switch(KeysTuple&& keysTuple, ValuesTuple&& valuesTuple, Key&& key, F&& f, Default&& def = {}) -> R
|
||||||
|
requires std::move_constructible<R> || std::same_as<R, void>
|
||||||
|
{
|
||||||
return Unpack(std::forward<KeysTuple>(keysTuple), [&]<typename... Keys>(Keys&&... keys) {
|
return Unpack(std::forward<KeysTuple>(keysTuple), [&]<typename... Keys>(Keys&&... keys) {
|
||||||
return Unpack(std::forward<ValuesTuple>(valuesTuple), [&]<typename... Values>(Values&&... values) {
|
return Unpack(std::forward<ValuesTuple>(valuesTuple), [&]<typename... Values>(Values&&... values) {
|
||||||
|
if constexpr(std::same_as<R, void>) {
|
||||||
|
FirstOf(Tuple{[&] {
|
||||||
|
return std::forward<Keys>(keys) == std::forward<Key>(key) ? (std::forward<F>(f)(std::forward<Values>(values)), true)
|
||||||
|
: false;
|
||||||
|
}...},
|
||||||
|
false);
|
||||||
|
} else {
|
||||||
return *FirstOf(Tuple{[&] {
|
return *FirstOf(Tuple{[&] {
|
||||||
return std::forward<Keys>(keys) == std::forward<Key>(key) ? std::forward<F>(f)(std::forward<Values>(values))
|
return std::forward<Keys>(keys) == std::forward<Key>(key) ? std::forward<F>(f)(std::forward<Values>(values))
|
||||||
: std::optional<R>{};
|
: std::optional<R>{};
|
||||||
|
@ -680,6 +692,7 @@ constexpr auto Switch(KeysTuple&& keysTuple, ValuesTuple&& valuesTuple, Key&& ke
|
||||||
.or_else([&] -> std::optional<R> {
|
.or_else([&] -> std::optional<R> {
|
||||||
return std::forward<Default>(def)();
|
return std::forward<Default>(def)();
|
||||||
});
|
});
|
||||||
|
};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue