matchit.cpp icon indicating copy to clipboard operation
matchit.cpp copied to clipboard

Support for std::expected

Open douaumont opened this issue 9 months ago • 2 comments

In C++23, there was a new type std::expected which is essentially Rust's Result.

I've tried to add some functionality to support it, and it seems to work. Should I submit a pull request if this is still relevant?

douaumont avatar Mar 19 '25 14:03 douaumont

In C++23, there was a new type std::expected which is essentially Rust's Result.

I've tried to add some functionality to support it, and it seems to work. Should I submit a pull request if this is still relevant?

Hi @douaumont Thanks for offering to contribution. I'm happy to accept it if you can guard the codes using something like #if __cplusplus >= 202402L (we do not want to break C++17 use cases).

BowenFu avatar Mar 25 '25 03:03 BowenFu

I guess it could be something like this

#include "matchit.h"
#include <expected>

// Generic ok pattern
constexpr auto ok = [](auto const pat) {
    using namespace matchit;
    return and_(
        // Check if it's an expected type with value
        pred([](auto&& exp) { return exp.has_value(); }),
        // Extract the value
        app([](auto&& exp) -> decltype(auto) { return exp.value(); }, pat)
    );
};

// Generic err pattern
constexpr auto err = [](auto const pat) {
    using namespace matchit;
    return and_(
        // Check if it's an expected type with error
        pred([](auto&& exp) { return !exp.has_value(); }),
        // Extract the error
        app([](auto&& exp) -> decltype(auto) { return exp.error(); }, pat)
    );
};

void process(auto&& exp) {  // Works with any std::expected<T, E>
    using namespace matchit;
    Id<decltype(exp.value())> val;
    Id<decltype(exp.error())> err_msg;

    match(exp)(
        pattern | ok(val)     = [&] { std::cout << "Value: " << *val; },
        pattern | err(err_msg) = [&] { std::cout << "Error: " << *err_msg; }
    );
}

int main() {
    process(std::expected<int, std::string>{42});  // Value: 42
    process(std::expected<double, int>{std::unexpected{5}});  // Error: 5
    return 0;
}

BowenFu avatar Mar 25 '25 12:03 BowenFu