diff --git a/A bite of pattern matching in C++.pdf b/A bite of pattern matching in C++.pdf new file mode 100644 index 0000000..51b29d9 Binary files /dev/null and b/A bite of pattern matching in C++.pdf differ diff --git a/Abstract.md b/Abstract.md deleted file mode 100644 index e1faf2f..0000000 --- a/Abstract.md +++ /dev/null @@ -1,22 +0,0 @@ -# Composable pattern objects are exactly what we need for pattern matching - -We will present a brand new pattern matching library, focusing on the power of composable pattern objects: makes it easy for users to extend and can minimize the codes users need to write. - -In our library [match(it)](https://github.com/BowenFu/matchit.cpp/blob/main/REFERENCE.md), we have 6 pattern primitives (`Expression Pattern`, `Wildcard Pattern`, `Predicate Pattern`, `Identifier Pattern`, `Match Guard`, `Ooo Pattern`) and 6 pattern combinators (`Or Pattern`, `And Pattern`, `Not Pattern`, `App Pattern`, `Destructure Pattern`, `At Pattern`). - -Pattern primitives are all objects. And pattern combinators are callables that return new objects. Let’s call these objects `pattern objects`. - -The most powerful two combinators can be `App Pattern` and `And Pattern`. Composing new patterns with them is much easier and cleaner than writing the `Matcher` and `Extractor` as described in the [current C++ Pattern Matching Proposal](https://wg21.link/P1371). - -There are some predefined composed patterns: `Some / None Pattern`, and `As Pattern`. - -`Some` can be simply defined as: -``` -constexpr auto some = [](auto const pat) { - return and_(app(cast, true), app(deref, pat)); -}; -``` - -The library covers all the pattern matching functionality described in the Proposal and also all functionality described in [Rust Reference Page](https://doc.rust-lang.org/stable/reference/patterns.html#literal-patterns). - -We will give our suggestions on the C++ Pattern Matching Proposal based on our experience with our library. \ No newline at end of file diff --git a/LICENSE b/LICENSE index 261eeb9..c9ab656 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2021] [Bowen Fu] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/develop/matchit/patterns.h b/develop/matchit/patterns.h index 92d55cb..597504e 100644 --- a/develop/matchit/patterns.h +++ b/develop/matchit/patterns.h @@ -309,8 +309,8 @@ namespace matchit constexpr auto execute() const { return mHandler(); } private: - Pattern const &mPattern; - Func const &mHandler; + Pattern const mPattern; + Func const mHandler; }; template diff --git a/include/matchit.h b/include/matchit.h index 03b6675..a096394 100644 --- a/include/matchit.h +++ b/include/matchit.h @@ -616,8 +616,8 @@ namespace matchit constexpr auto execute() const { return mHandler(); } private: - Pattern const &mPattern; - Func const &mHandler; + Pattern const mPattern; + std::conditional_t, Func const&, Func const> mHandler; }; template diff --git a/sample/CMakeLists.txt b/sample/CMakeLists.txt index 39162e8..2ed2e75 100644 --- a/sample/CMakeLists.txt +++ b/sample/CMakeLists.txt @@ -48,6 +48,7 @@ Extractor-Pattern Predicate-based-Discriminator Closed-Class-Hierarchy Matcher-within +visit ) foreach(sample ${MATCHIT_SAMPLES}) diff --git a/sample/Red-black-Tree-Rebalancing.cpp b/sample/Red-black-Tree-Rebalancing.cpp index fc3cc1c..c376c9b 100644 --- a/sample/Red-black-Tree-Rebalancing.cpp +++ b/sample/Red-black-Tree-Rebalancing.cpp @@ -28,6 +28,7 @@ bool operator==(Node const &lhs, Node const &rhs) lhs.value == rhs.value && lhs.rhs == rhs.rhs; } +#if 0 template void Node::balance() { @@ -81,6 +82,55 @@ void Node::balance() ); } +#else + +template +void Node::balance() +{ + using namespace matchit; + + constexpr auto dsN = [](auto &&color, auto &&lhs, auto &&value, auto &&rhs) + { + return and_(app(&Node::color, color), app(&Node::lhs, lhs), + app(&Node::value, value), app(&Node::rhs, rhs)); + }; + + constexpr auto blackN = [dsN](auto &&lhs, auto &&value, auto &&rhs) + { + return dsN(Black, lhs, value, rhs); + }; + + constexpr auto redN = [dsN](auto &&lhs, auto &&value, auto &&rhs) + { + return dsN(Red, lhs, value, rhs); + }; + + Id>> a, b, c, d; + Id x, y, z; + Id self; + *this = match(*this)( + pattern | blackN(some(redN(some(redN(a, x, b)), y, c)), z, d) // left-left case + = [&] + { return Node{Red, std::make_shared(Black, *a, *x, *b), *y, + std::make_shared(Black, *c, *z, *d)}; }, + pattern | blackN(some(redN(a, x, some(redN(b, y, c)))), z, d) // left-right case + = [&] + { return Node{Red, std::make_shared(Black, *a, *x, *b), *y, + std::make_shared(Black, *c, *z, *d)}; }, + pattern | blackN(a, x, some(redN(some(redN(b, y, c)), z, d))) // right-left case + = [&] + { return Node{Red, std::make_shared(Black, *a, *x, *b), *y, + std::make_shared(Black, *c, *z, *d)}; }, + pattern | blackN(a, x, some(redN(b, y, some(redN(c, z, d))))) // right-right case + = [&] + { return Node{Red, std::make_shared(Black, *a, *x, *b), *y, + std::make_shared(Black, *c, *z, *d)}; }, + pattern | self = expr(self) // do nothing + ); +} + +#endif + int main() { auto x = std::make_shared>(Color::Red, std::shared_ptr>{}, diff --git a/sample/visit.cpp b/sample/visit.cpp new file mode 100644 index 0000000..ffde9f2 --- /dev/null +++ b/sample/visit.cpp @@ -0,0 +1,52 @@ +#include "matchit.h" + +#include +#include + +template +auto constexpr visitPat = [](auto func) +{ + using namespace matchit; + + return as(meet([func](auto&& param) { + func(param); + return true; + })); +}; + +template +auto constexpr visit = [](auto func) +{ + using namespace matchit; + + return pattern | visitPat(func) = []{}; +}; + +template +void print(T&& x) +{ + using namespace matchit; + + match(x)( + visit( + [](const std::string& text) { + std::cout << "Text message: " << text << std::endl; + }), + visit( + [](const int32_t num) { + std::cout << "Number: " << num << std::endl; + }) + ); +} + +int main() +{ + using namespace matchit; + + std::variant v1 = "123"; + std::variant v2 = 123; + + print(v1); + print(v2); + return 0; +}