diff --git a/examples/src/switch.cpp b/examples/src/switch.cpp index 927c082..20aecee 100644 --- a/examples/src/switch.cpp +++ b/examples/src/switch.cpp @@ -20,4 +20,11 @@ auto main() -> int { [] { return 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); }; diff --git a/include/utempl/utils.hpp b/include/utempl/utils.hpp index 999f2ca..fc87b83 100644 --- a/include/utempl/utils.hpp +++ b/include/utempl/utils.hpp @@ -644,11 +644,14 @@ constexpr auto Enumerate(Tuple&& tuple) { }; template - requires requires { T{}; } + requires std::same_as || requires { T{}; } constexpr auto kDefaultCreator = [] { return T{}; }; +template <> +constexpr auto kDefaultCreator = [] {}; + namespace impl { template @@ -657,29 +660,39 @@ concept ComparableSwitchConcept = decltype(Unpack(std::declval(), []< }))::kValue; template -concept CallableSwitchConcept = decltype(Unpack(std::declval(), [](Ts&&...) { - return kWrapper<(std::convertible_to, std::optional> && ...)>; -}))::kValue; +concept CallableSwitchConcept = std::same_as || decltype(Unpack(std::declval(), [](Ts&&...) { + return kWrapper<(std::convertible_to, std::optional> && ...)>; + }))::kValue; } // namespace impl -template Key, impl::CallableSwitchConcept F, std::invocable Default = decltype(kDefaultCreator)> -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 || std::same_as +{ return Unpack(std::forward(keysTuple), [&](Keys&&... keys) { return Unpack(std::forward(valuesTuple), [&](Values&&... values) { - return *FirstOf(Tuple{[&] { - return std::forward(keys) == std::forward(key) ? std::forward(f)(std::forward(values)) - : std::optional{}; - }...}, - std::optional{}) - .or_else([&] -> std::optional { - return std::forward(def)(); - }); + if constexpr(std::same_as) { + FirstOf(Tuple{[&] { + return std::forward(keys) == std::forward(key) ? (std::forward(f)(std::forward(values)), true) + : false; + }...}, + false); + } else { + return *FirstOf(Tuple{[&] { + return std::forward(keys) == std::forward(key) ? std::forward(f)(std::forward(values)) + : std::optional{}; + }...}, + std::optional{}) + .or_else([&] -> std::optional { + return std::forward(def)(); + }); + }; }); }); };