Last active
October 8, 2024 00:42
-
-
Save petar-andrejic/d72a1219f927adb4c89e1041327eae13 to your computer and use it in GitHub Desktop.
Match statements in C++20
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <print> | |
#include <variant> | |
template<class... Ts> | |
struct Pattern : Ts... { | |
using Ts::operator()...; | |
}; | |
template<class Variant> | |
struct Match { | |
const Variant &v; | |
explicit Match(const Variant &v) : v(v) {}; | |
template<class Pattern> | |
constexpr auto operator<<(const Pattern &p) const { | |
return std::visit(p, v); | |
} | |
}; | |
#define match(v) Match(v) << Pattern | |
// Concept alias: use as a constraint on the match arm to forbid implicit conversion! | |
template<typename U, typename V> | |
concept Case = std::same_as<U, V>; | |
int main() { | |
std::variant<long, int, float> v = 5; | |
int shouldBeFive = 0; | |
int shouldBeSix = 0; | |
shouldBeSix = match(v) { | |
[&](Case<int> auto val){ | |
std::println("An integer: {}", val); | |
shouldBeFive = val; | |
return 6; | |
}, | |
[](auto) { | |
std::println("Not implemented"); | |
return 0; | |
}, | |
}; | |
std::println("shouldBeFive is: {}", shouldBeFive); | |
std::println("shouldBeSix is: {}", shouldBeSix); | |
v = 3l; | |
match(v) { | |
[](Case<int> auto val) { | |
std::println("An integer: {}", val); | |
}, | |
[](Case<float> auto val) { | |
std::println("A float: {}", val); | |
}, | |
[](auto val) { | |
std::println("The default match (long): {}", val); | |
}, | |
}; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Because of constexpr everything inlines if possible, compiling down to jump tables: https://godbolt.org/z/aa38jG988 https://godbolt.org/z/qdanrqdr8 https://godbolt.org/z/EM7zK59YM