Skip to content

Commit

Permalink
feat: Implement pattern check with test
Browse files Browse the repository at this point in the history
  • Loading branch information
cwahn committed Apr 10, 2024
1 parent 4606b1a commit 9c81255
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 28 deletions.
4 changes: 1 addition & 3 deletions include/efp/enum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,6 @@ namespace detail {
public:
constexpr static uint8_t alt_num = sizeof...(As) + 1;

// constexpr static uint8_t switch_size = power_2_ceiling(alt_num);

// Default constructor initializes the first alternative with default constructor
EnumBase() : _index {0} {
new (reinterpret_cast<A*>(&_storage)) A {};
Expand Down Expand Up @@ -410,7 +408,7 @@ namespace detail {

private:
template<typename Alt>
struct AltIndex: Find<IsSameUnary<ReferenceRemoved<Alt>>::template Binded, A, As...> {};
using AltIndex = Find<IsSameUnary<ReferenceRemoved<Alt>>::template Binded, A, As...>;

// Assume that the index is altready bounded
template<uint8_t i>
Expand Down
57 changes: 40 additions & 17 deletions include/efp/maybe.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,22 @@
#include "efp/trait.hpp"

namespace efp {

struct Nothing {};

constexpr Nothing nothing;

// Specialization of Enum for Maybe

template<typename A>
using Maybe = Enum<Nothing, A>;

template<typename A>
struct IsMaybe: False {};

template<typename A>
struct IsMaybe<Maybe<A>>: True {};

template<typename A>
class Enum<Nothing, A>: public detail::EnumBase<Nothing, A> {
public:
Expand Down Expand Up @@ -44,22 +54,44 @@ class Enum<Nothing, A>: public detail::EnumBase<Nothing, A> {
}

template<typename F>
auto fmap(const F& f) -> Enum<Nothing, InvokeResult<F, A>> {
static Enum<Nothing, A> pure(const A& a) {
return a;
}

template<typename F>
auto fmap(const F& f) -> Enum<Nothing, InvokeResult<F, A>> const {
if (has_value())
return f(value());
else
return nothing;
}
};

template<typename A>
using Maybe = Enum<Nothing, A>;
template<typename F>
auto ap(const Enum<Nothing, F>& mf) -> Enum<Nothing, InvokeResult<F, A>> const {
if (has_value() && mf.has_value())
return mf.value()(value());
else
return nothing;
}

template<typename A>
struct IsMaybe: False {};
template<typename F>
auto bind(const F& f)
-> EnableIf<IsMaybe<InvokeResult<F, A>>::value, InvokeResult<F, A>> const {
if (has_value())
return f(value());
else
return nothing;
}

template<typename A>
struct IsMaybe<Maybe<A>>: True {};
template<typename F>
auto operator>>=(const F& f)
-> EnableIf<IsMaybe<InvokeResult<F, A>>::value, InvokeResult<F, A>> const {
if (has_value())
return f(value());
else
return nothing;
}
};

// Element specializetion for Maybe
template<typename A>
Expand Down Expand Up @@ -102,15 +134,6 @@ auto bind(const Maybe<A>& ma, const F& f)
return nothing;
}

template<typename A, typename F>
auto operator>>=(const Maybe<A>& ma, const F& f)
-> EnableIf<IsMaybe<InvokeResult<F, A>>::value, InvokeResult<F, A>> {
if (ma)
return f(ma.value());
else
return nothing;
}

} // namespace efp

#endif
16 changes: 8 additions & 8 deletions include/efp/meta.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -820,24 +820,24 @@ constexpr A _product(const A (&as)[n]) {
}

// All
// ! Deprecated because of performance issue. Use foldl instead
// ! Not suitable for library implementation because of compile-time performance issue
template<typename A, typename... As>
struct All: Bool<_all({A::value, As::value...})> {};
using All = Bool<_all({A::value, As::value...})>;

// Any
// ! Deprecated because of performance issue. Use foldl instead
// ! Not suitable for library implementation because of compile-time performance issue
template<typename A, typename... As>
struct Any: Bool<_any({A::value, As::value...})> {};
using Any = Bool<_any({A::value, As::value...})>;

// Minimum
// ! Deprecated because of performance issue. Use foldl instead
// ! Not suitable for library implementation because of compile-time performance issue
template<typename A, typename... As>
struct Minimum: CtConst<typename A::value_type, _minimum({A::value, As::value...})> {};
using Mininum = CtConst<typename A::value_type, _minimum({A::value, As::value...})>;

// Maximum
// ! Deprecated because of performance issue. Use foldl instead
// ! Not suitable for library implementation because of compile-time performance issue
template<typename A, typename... As>
struct Maximum: CtConst<typename A::value_type, _maximum({A::value, As::value...})> {};
using Maximum = CtConst<typename A::value_type, _maximum({A::value, As::value...})>;

// Common
template<typename... As>
Expand Down
1 change: 1 addition & 0 deletions test/efp/enum_test.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ TEST_CASE("enum_match") {
// ! Sould be failed to get compiled and show static assert message on top
// a.match([&](int x) { b += 1; }, [&](double _) { b += 1; });
// a.match([&](int x) { b += 1; }, [&](False _) {}, [&]() {});
// a.match([&]() {}, [&](int x) { b += 1; });

CHECK(b == 0.);
}
Expand Down

0 comments on commit 9c81255

Please sign in to comment.