Skip to content

Instantly share code, notes, and snippets.

@Siapran
Created February 28, 2020 20:18
Show Gist options
  • Save Siapran/8dfc577e69bc33cdc118ff6aebf18242 to your computer and use it in GitHub Desktop.
Save Siapran/8dfc577e69bc33cdc118ff6aebf18242 to your computer and use it in GitHub Desktop.
#ifndef ANY_LENS_HPP
#define ANY_LENS_HPP
#include <lager/lenses.hpp>
#include <memory>
#include <utility>
#include <type_traits>
namespace detail {
template <typename Whole, typename Part>
struct ILens {
virtual Part view(Whole const &) const = 0;
virtual Whole set(Whole const &, Part const &) const = 0;
};
template <typename Lens, typename Whole, typename Part>
struct LensHolder : public ILens<Whole, Part> {
Lens value;
template <typename T>
LensHolder(T &&other) : value{std::forward<T>(other)} {}
Part view(Whole const &w) const override {
return ::lager::view(value, w);
}
Whole set(Whole const &w, Part const &p) const override {
return ::lager::set(value, w, p);
}
};
}
template <typename Whole, typename Part>
class any_lens {
std::shared_ptr<detail::ILens<Whole, Part> const> m_holder;
public:
any_lens(any_lens const &) = default;
any_lens(any_lens &&) = default;
any_lens &operator=(any_lens const &) = default;
any_lens &operator=(any_lens &&) = default;
template <typename Lens,
typename std::enable_if<
!std::is_same_v<std::decay_t<Lens>,
std::decay_t<any_lens>>, int>::type = 0>
any_lens(Lens &&lens) :
m_holder{new detail::LensHolder<Lens, Whole, Part>{std::forward<Lens>(lens)}}
{}
auto get() const {
return zug::comp([lens = m_holder](auto&& f) {
return [&, f](auto&& p) {
return f(lens->view(std::forward<decltype(p)>(p)))([&](auto&& x) {
return lens->set(std::forward<decltype(p)>(p),
std::forward<decltype(x)>(x));
});
};
});
}
};
#endif // ANY_LENS_HPP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment