Skip to content

Commit

Permalink
Merge pull request #128 from daniel-j-h/match
Browse files Browse the repository at this point in the history
Pattern Matching for Sum Types via `.match` Member Function
  • Loading branch information
artemp committed Nov 21, 2016
2 parents 3c17c37 + 720c237 commit ed84def
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 4 deletions.
17 changes: 17 additions & 0 deletions include/mapbox/variant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <functional>

#include <mapbox/recursive_wrapper.hpp>
#include <mapbox/variant_visitor.hpp>

// clang-format off
// [[deprecated]] is only available in C++14, use this for the time being
Expand Down Expand Up @@ -872,6 +873,22 @@ class variant
return detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f));
}

// match
// unary
template <typename... Fs>
auto VARIANT_INLINE match(Fs&&... fs) const
-> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)))
{
return variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...));
}
// non-const
template <typename... Fs>
auto VARIANT_INLINE match(Fs&&... fs)
-> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)))
{
return variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...));
}

~variant() noexcept // no-throw destructor
{
helper_type::destroy(type_index, &data);
Expand Down
2 changes: 2 additions & 0 deletions include/mapbox/variant_visitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ struct visitor;
template <typename Fn>
struct visitor<Fn> : Fn
{
using type = Fn;
using Fn::operator();

visitor(Fn fn) : Fn(fn) {}
Expand All @@ -18,6 +19,7 @@ struct visitor<Fn> : Fn
template <typename Fn, typename... Fns>
struct visitor<Fn, Fns...> : Fn, visitor<Fns...>
{
using type = visitor;
using Fn::operator();
using visitor<Fns...>::operator();

Expand Down
43 changes: 39 additions & 4 deletions test/lambda_overload_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ void test_singleton_variant()
apply_visitor(make_visitor([](int) {}), singleton);
}

#ifdef HAS_CPP14_SUPPORT
void test_lambda_overloads_sfinae()
#ifdef HAS_CPP14_SUPPORT
{
variant<int, float, std::vector<int>> var;

Expand All @@ -76,17 +76,52 @@ void test_lambda_overloads_sfinae()
var = std::vector<int>{4, 5, 6};
apply_visitor(visitor, var);
}
#else
{
}
#endif

void test_match_singleton()
{
variant<int> singleton = 5;
singleton.match([](int) {});
}

void test_match_overloads()
{
Either<Error, Response> rv;

rv = Response{};

rv.match([](Response) { std::cout << "Response\n"; }, //
[](Error) { std::cout << "Error\n"; }); //
}

void test_match_overloads_capture()
{
Either<Error, Response> rv;

rv = Error{};

int ok = 0;
int err = 0;

rv.match([&](Response) { ok += 1; }, //
[&](Error) { err += 1; }); //

std::cout << "Got " << ok << " ok, " << err << " err" << std::endl;
}

int main()
{
test_lambda_overloads();
test_singleton_variant();
test_lambda_overloads_capture();

#ifdef HAS_CPP14_SUPPORT
test_lambda_overloads_sfinae();
#endif

test_match_singleton();
test_match_overloads();
test_match_overloads_capture();
}

#undef HAS_CPP14_SUPPORT

0 comments on commit ed84def

Please sign in to comment.