This is an experimental library that has evolved to P2688
This is an experimental library that has evolved to P2688
This is an experimental library that has evolved to P2688, being proposed for C++26.
MPark.Patterns is an experimental pattern matching library for C++17.
It determines whether a given value matches a pattern and, if it does, binds the desired portions of the value to a handler.
Pattern matching has been introduced to many programming languages outside of the functional world, and this library draws inspiration from languages such as Haskell, OCaml, Rust, Scala, and Swift.
#include
#include
void fizzbuzz() {
using namespace mpark::patterns;
for (int i = 1; i ...)(
pattern(...) = [](...) { /* ... */ },
pattern(...) = [](...) { /* ... */ },
// ...
);An expression pattern matches if the value compares equal to the given expression.
Given an expression e and a value x, e == x must be a valid expression.
int factorial(int n) {
using namespace mpark::patterns;
return match(n)(pattern(0) = [] { return 1; },
// ^ expression
pattern(_) = [n] { return n * factorial(n - 1); });
}An arg pattern matches any value, and binds the value by passing it to the corresponding handler. This pattern can be repeated in a single pattern, and they match independent of each other.
None.
argarg()int factorial(int n) {
using namespace mpark::patterns;
return match(n)(pattern(0) = [] { return 1; },
pattern(arg) = [](auto n) { return n * factorial(n - 1); });
// ^^^ arg
}…cpp auto t = std::make_tuple(101, "hello", 1.1);
// C++17 Structured Binding: const auto & [x, y, z] = t; // ...
// MPark.Patterns: using namespace mpark::patterns; IDENTIFIERS(x, y, z); match(t)( pattern(ds(x, y, z)) = [](auto &&x, auto &&y, auto &&z) { /* ... */ }); // ^^^^^^^^^^^ destructure
__NOTE__: The top-level is wrapped by a `tuple`, allowing us to write:
```cpp
void fizzbuzz() {
for (int i = 1; i ()`,
`T` must satisfy one of the following conditions:
1. `std::is_polymorphic_v == true`, or
2. `std::is_class_v == true` and `std::variant_size` is a complete type, or
3. `x.any_cast()` or `any_cast(&x)` is a valid expression
- If (1), `dynamic_cast(&x)` must be a valid expression,
where `U'` is pointer to `U` with the same cv-qualifiers as `decltype(x)`
- If (2), `x.get_if()` or `get_if(&x)` must be a valid expression
#### Syntax
- `as()`
#### Examples
```cpp
struct Shape { virtual ~Shape() = default; };
struct Circle : Shape {};
struct Square : Shape {};
std::unique_ptr shape = std::make_unique();
using namespace mpark::patterns;
match(shape)(pattern(some(as(_))) = [] { std::cout (_))) = [] { std::cout (_)) = [] { std::cout (_)) = [] { std::cout
decltype(auto) apply(F &&f, Tuple &&t) {
using namespace mpark::patterns;
return match(std::forward(t))(
pattern(ds(variadic(arg))) = std::forward(f));
}and even C++17 std::visit:
template
decltype(auto) visit(F &&f, Vs &&... vs) {
using namespace mpark::patterns;
return match(std::forward(vs)...)(
pattern(variadic(vis(arg))) = std::forward(f));
}We can even get a little fancier:
int x = 42;
auto y = std::make_tuple(101, "hello", 1.1);
using namespace mpark::patterns;
match(x, y)(
pattern(arg, ds(variadic(arg))) = [](const auto &... xs) {
int dummy[] = { (std::cout ) { /* ... */ };`
#### Examples
```cpp
using namespace mpark::patterns;
IDENTIFIERS(x, y);
match(101, 202)(
pattern(x, x) = [](int) { std::cout y) { std::cout pairs = {{0, 1}, {1, 1}, {0, 0}, {0, 2}};
for ((0, x) : pairs) {
std::cout pairs = {{0, 1}, {1, 1}, {0, 0}, {0, 2}};
for (const auto &p : pairs) {
using namespace mpark::patterns;
if_let (pattern(ds(0, arg)) = p) = [](auto x) {
std::cout pairs = {{0, 1}, {1, 1}, {0, 0}, {0, 2}};
using namespace mpark::patterns;
for_let (pattern(ds(0, arg)) = pairs) = [](auto x) {
std::cout pairs = {{0, 1}, {1, 1}, {0, 0}, {0, 2}};
using namespace mpark::patterns;
for_let (pattern(ds(0, arg)) = pairs) = [](auto x) {
if (x == 1) return Break;
std::cout pairs = {{0, 1}, {1, 1}, {0, 0}, {0, 2}};
using namespace mpark::patterns;
for_let (pattern(ds(0, arg)) = pairs) = [](auto x) {
if (x == 0) return Continue;
std::cout << x << ' ';
return Continue;
};
// prints: "1 2 "This library requires a standard conformant C++17 compiler. The following compilers are continously tested:
| Compiler | Operating System | Version String |
|---|---|---|
| GCC 7.4.0 | Ubuntu 16.04.6 LTS | g++-7 (Ubuntu 7.4.0-1ubuntu1 |
| GCC 8.1.0 | Ubuntu 16.04.6 LTS | g++-8 (Ubuntu 8.1.0-5ubuntu1~16.04) 8.1.0 |
| Clang 5.0.0 | Ubuntu 16.04.6 LTS | clang version 5.0.0-3~16.04.1 (tags/RELEASE_500/final) |
| Clang 6.0.0 | Ubuntu 16.04.6 LTS | clang version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) |
| Clang 7.1.0 | Ubuntu 16.04.6 LTS | clang version 7.1.0-svn353565-1 |
MPARK_PATTERNS_INCLUDE_TESTS:BOOL (default: OFF)
Build tests.
Refer to test/README.md.
Distributed under the Boost Software License, Version 1.0.
No open issues yet, or sync has not completed.