Skip to content

Commit

Permalink
Merge pull request #216 from Siapran/force_opt-fix
Browse files Browse the repository at this point in the history
Enable writing to force_opt lens with non-opt value.
  • Loading branch information
arximboldi authored Nov 13, 2024
2 parents 338ed6b + db24eb1 commit 4865197
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 7 deletions.
19 changes: 16 additions & 3 deletions lager/lenses/optional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ struct add_opt
using type = std::optional<std::decay_t<T>>;
};

template <typename T>
struct is_optional : std::false_type
{};

template <typename T>
struct is_optional<std::optional<T>> : std::true_type
{};

} // namespace detail

//! @defgroup lenses
Expand Down Expand Up @@ -110,7 +118,7 @@ auto value_or(T&& t)
{
return zug::comp([t = std::forward<T>(t)](auto&& f) {
return [&, f = LAGER_FWD(f)](auto&& whole) {
return f(LAGER_FWD(whole).value_or(std::move(t)))(
return f(LAGER_FWD(whole).value_or(t))(
[&](auto&& x) { return LAGER_FWD(x); });
};
});
Expand Down Expand Up @@ -141,8 +149,13 @@ ZUG_INLINE_CONSTEXPR auto or_default = value_or();
ZUG_INLINE_CONSTEXPR auto force_opt = zug::comp([](auto&& f) {
return [f = LAGER_FWD(f)](auto&& p) {
using opt_t = std::optional<std::decay_t<decltype(p)>>;
return f(opt_t{LAGER_FWD(p)})(
[&](auto&& x) { return LAGER_FWD(x).value_or(LAGER_FWD(p)); });
auto opt = opt_t{LAGER_FWD(p)};
return f(std::move(opt))([&](auto&& x) -> decltype(auto) {
if constexpr (detail::is_optional<std::decay_t<decltype(x)>>::value)
return LAGER_FWD(x).value_or(*std::move(opt));
else
return LAGER_FWD(x);
});
};
});

Expand Down
22 changes: 18 additions & 4 deletions test/lenses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
#include <lager/lenses/at_or.hpp>
#include <lager/lenses/attr.hpp>
#include <lager/lenses/optional.hpp>
#include <lager/lenses/variant.hpp>
#include <lager/lenses/tuple.hpp>
#include <lager/lenses/variant.hpp>

#include <array>

Expand Down Expand Up @@ -423,6 +423,21 @@ TEST_CASE("lenses, bind_opt")
}
}


TEST_CASE("lenses::force_opt with bind_opt", "[lenses][force_opt][bind_opt]")
{
auto opt_member_lens = attr(&yearday::day) | force_opt;
auto bound_opt_member = bind_opt(opt_member_lens);

CHECK(view(bound_opt_member, std::optional{yearday{1, 1}}) ==
std::optional{1});
CHECK(view(bound_opt_member, std::optional<yearday>{}) == std::nullopt);
CHECK(set(bound_opt_member, std::optional{yearday{1, 1}}, 1)->day == 1);
CHECK(set(bound_opt_member, std::optional{yearday{1, 1}}, std::optional{1})
->day == 1);
CHECK(!set(bound_opt_member, std::optional<yearday>{}, std::nullopt));
}

TEST_CASE("lenses::zip pair", "[lenses][zip][pair]")
{
struct foo
Expand All @@ -433,9 +448,8 @@ TEST_CASE("lenses::zip pair", "[lenses][zip][pair]")
std::pair<foo, int> baz{{42}, 256};
auto zipped = zip(attr(&foo::value), lager::identity);

baz = over(zipped, baz, [](auto x) {
return std::pair{x.second, x.first};
});
baz =
over(zipped, baz, [](auto x) { return std::pair{x.second, x.first}; });

CHECK(baz.first.value == 256);
CHECK(baz.second == 42);
Expand Down

0 comments on commit 4865197

Please sign in to comment.