| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
- #pragma once
- #include <type_traits>
- #include <jvalidate/constraint/extension_constraint.h>
- #include <jvalidate/forward.h>
- #include <jvalidate/status.h>
- namespace jvalidate::extension {
- struct VisitorBase {
- virtual ~VisitorBase() = default;
- };
- template <typename E>
- concept Constraint = std::is_base_of_v<constraint::ExtensionConstraint::Impl, E>;
- namespace detail {
- template <Constraint E> struct TypedVisitor : VisitorBase {
- virtual Status visit(E const & cons) const = 0;
- };
- template <Constraint E, typename CRTP> struct TypedVisitorImpl : TypedVisitor<E> {
- Status visit(E const & cons) const final {
- return static_cast<CRTP const *>(this)->dispatch(cons);
- }
- };
- }
- template <typename CRTP> struct ConstraintBase : constraint::ExtensionConstraint::Impl {
- Status visit(VisitorBase const & visitor) const final {
- return dynamic_cast<detail::TypedVisitor<CRTP> const &>(visitor).visit(
- static_cast<CRTP const &>(*this));
- }
- };
- template <typename CRTP, typename... Es> class Visitor {
- private:
- template <Adapter A, typename V> class Impl : public detail::TypedVisitorImpl<Es, Impl<A, V>>... {
- public:
- Impl(Visitor const * self, A const & document, V const & visitor)
- : self_(self), document_(document), visitor_(visitor) {}
- using detail::TypedVisitorImpl<Es, Impl>::visit...;
- template <Constraint E> Status dispatch(E const & cons) const {
- // static_assert(Visitable<CRTP, E, A, V>, "Must implement all visitation functions");
- return static_cast<CRTP const *>(self_)->visit(cons, document_, visitor_);
- }
- private:
- Visitor const * self_;
- A const & document_;
- V const & visitor_;
- };
- public:
- template <Adapter A, typename V>
- Status operator()(constraint::ExtensionConstraint const & cons, A const & document,
- V const & visitor) const {
- return cons.pimpl->visit(Impl<A, V>{this, document, visitor});
- }
- };
- }
|