diff --git a/include/ptn/core/match_builder.hpp b/include/ptn/core/match_builder.hpp index 3f7807e6..20d497f5 100644 --- a/include/ptn/core/match_builder.hpp +++ b/include/ptn/core/match_builder.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #if PTN_USE_CONCEPTS #include @@ -17,9 +18,9 @@ namespace ptn { /* free match function forward declaration */ - template + template constexpr auto - match(U &&) noexcept(std::is_nothrow_constructible_v, U &&>); + match(T &&) noexcept(std::is_nothrow_constructible_v, T &&>); } // namespace ptn namespace ptn::detail { @@ -89,35 +90,45 @@ namespace ptn::core { class match_builder { TV value_; std::tuple cases_; - using ctor_tag_t = ctor_tag; - - template - friend constexpr auto ::ptn::match(U &&) noexcept( - std::is_nothrow_constructible_v, U &&>); - + using ctor_tag_t = ptn::core::ctor_tag; /* make all specializations of match_builder mutual friends */ template friend class match_builder; - template + template #if PTN_USE_CONCEPTS - requires std::constructible_from, Tuple> + requires std::constructible_from && + std::constructible_from, Tuple> #endif - explicit constexpr match_builder(TV &&v, Tuple &&cs, ctor_tag_t) - : value_(std::forward(v)), cases_(std::forward(cs)) { + explicit constexpr match_builder(TV2 &&v, Tuple &&cs, ctor_tag_t) + : value_(std::forward(v)), cases_(std::forward(cs)) { } public: - // with + // Correctly place template & requires for create + template +#if PTN_USE_CONCEPTS + requires std::constructible_from, Tuple> +#endif + static constexpr auto create(VArg &&v, Tuple &&cs) + -> match_builder, Cases...> { + using result_t = match_builder, Cases...>; + return result_t( + std::forward(v), std::forward(cs), ctor_tag{}); + } + + // with (lvalue) template constexpr auto with(Pattern p, Handler h) & { using pair_t = std::pair; auto new_cases = std::tuple_cat( cases_, std::make_tuple(pair_t{std::move(p), std::move(h)})); + // use brace-init to construct the returned match_builder return match_builder( value_, std::move(new_cases), ctor_tag_t{}); } + // with (rvalue) template constexpr auto with(Pattern p, Handler h) && { using pair_t = std::pair; @@ -138,7 +149,8 @@ namespace ptn::core { decltype(ptn::detail::run_handler( std::declval &>(), std::declval()))>; R out{}; - bool done = false; + bool done = false; + auto try_one = [&](auto &c) { if (done) return; @@ -199,4 +211,4 @@ namespace ptn::core { return std::move(*this).with(std::move(e.pattern), std::move(e.handler)); } }; -} // namespace ptn::core \ No newline at end of file +} // namespace ptn::core diff --git a/include/ptn/patternia.hpp b/include/ptn/patternia.hpp index b46d4823..d83090b7 100644 --- a/include/ptn/patternia.hpp +++ b/include/ptn/patternia.hpp @@ -18,8 +18,8 @@ namespace ptn { constexpr auto match(T &&value) noexcept( std::is_nothrow_constructible_v, T &&>) { using V = std::decay_t; - return core::match_builder( - V(std::forward(value)), std::tuple<>{}, core::ctor_tag{}); + return core::match_builder::create( + V(std::forward(value)), std::tuple<>{}); } }; // namespace ptn @@ -31,7 +31,7 @@ namespace ptn { #if PTN_ENABLE_RELATIONAL_PATTERN // clang-format off -# include +#include // clang-format on #endif