mutable
A Database System for Research and Fast Prototyping
Loading...
Searching...
No Matches
Visitor.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <mutable/mutable-config.hpp>
5#include <mutable/util/fn.hpp>
9#include <optional>
10#include <type_traits>
11
12
13namespace m {
14
19
20namespace detail {
21
28template<typename ConcreteVisitor, typename Base>
29struct Visitor : crtp<ConcreteVisitor, Visitor, Base>
30{
31 using crtp<ConcreteVisitor, Visitor, Base>::actual;
32
34 static constexpr bool is_const = std::is_const_v<Base>;
35
37 using base_type = Base;
38
40 using visitor_type = ConcreteVisitor;
41
43 template<typename T>
44 using Const = std::conditional_t<is_const, const T, T>;
45
47 virtual ~Visitor() { }
48
50 virtual void operator()(base_type &obj) { obj.accept(actual()); }
51};
52
58template<typename ConcreteVisitor, typename Base, typename Class, typename... Classes>
59struct visitor_method_helper : visitor_method_helper<ConcreteVisitor, Base, Classes...>
60{
61 using super = visitor_method_helper<ConcreteVisitor, Base, Classes...>;
62 template<typename T> using Const = typename super::template Const<T>;
63 using super::operator();
64 virtual void operator()(Const<Class>&) { }
65};
67template<typename ConcreteVisitor, typename Base, typename Class>
68struct visitor_method_helper<ConcreteVisitor, Base, Class> : Visitor<ConcreteVisitor, Base>
69{
71 template<typename T> using Const = typename super::template Const<T>;
72 using super::operator();
73 virtual void operator()(Const<Class>&) { }
74};
75
79template<typename ConcreteVisitor, typename Base, typename... Hierarchy>
80struct VisitorImpl : visitor_method_helper<ConcreteVisitor, Base, Hierarchy...>
81{
82 using super = visitor_method_helper<ConcreteVisitor, Base, Hierarchy...>;
83 template<typename T> using Const = typename super::template Const<T>;
84 using super::operator();
85};
86
90template<typename Callable, typename ResultType, typename Visitor, typename Class, typename... Classes>
91struct stl_visit_helper : stl_visit_helper<Callable, ResultType, Visitor, Classes...>
92{
93 using super = stl_visit_helper<Callable, ResultType, Visitor, Classes...>;
94
95 stl_visit_helper(Callable &callable, std::optional<some<ResultType>> &result) : super(callable, result) { }
96
97 using super::operator();
98 void operator()(typename Visitor::template Const<Class> &obj) override {
99 if constexpr (std::is_same_v<void, ResultType>) { this->callable(obj); }
100 else { super::result = m::some<ResultType>(this->callable(obj)); }
101 }
102};
105template<typename Callable, typename ResultType, typename Visitor, typename Class>
106struct stl_visit_helper<Callable, ResultType, Visitor, Class> : Visitor
107{
108 Callable &callable;
109 std::optional<some<ResultType>> &result;
110
111 stl_visit_helper(Callable &callable, std::optional<some<ResultType>> &result) : callable(callable), result(result) { }
112
113 using Visitor::operator();
114 void operator()(typename Visitor::template Const<Class> &obj) override {
115 if constexpr (std::is_same_v<void, ResultType>) { this->callable(obj); }
116 else { result = m::some<ResultType>(this->callable(obj)); }
117 }
118};
119
120}
121
137template<typename Callable, typename Visitor, typename Base, typename... Hierarchy>
138auto visit(Callable &&callable, Base &obj, m::tag<Callable>&& = m::tag<Callable>())
139{
141 using result_type = std::common_type_t< std::invoke_result_t<Callable, typename Visitor::template Const<Hierarchy>&>... >;
142
143 std::optional<some<result_type>> result;
144
145 /*----- Create a `visit_helper` and then invoke it on the `obj`. -----*/
146 detail::stl_visit_helper<Callable, result_type, Visitor, Hierarchy...> V(callable, result);
147 try { V(obj); } catch (visit_stop_recursion) { }
148 if constexpr (not std::is_same_v<void, result_type>) {
149 return std::move(V.result->value);
150 } else {
151 return; // result is `void`
152 }
153}
154
155}
156
157
166#define M_MAKE_STL_VISITABLE(VISITOR, BASE_CLASS, CLASS_LIST) \
167 template<typename Callable> \
168 auto visit(Callable &&callable, BASE_CLASS &obj, m::tag<VISITOR>&& = m::tag<VISITOR>()) { \
169 return m::visit<Callable, VISITOR, BASE_CLASS CLASS_LIST(M_COMMA_PRE)>(std::forward<Callable>(callable), obj); \
170 }
171
181#define M_DECLARE_VISITOR(VISITOR_NAME, BASE_CLASS, CLASS_LIST) \
182 struct VISITOR_NAME : m::detail::VisitorImpl<VISITOR_NAME, BASE_CLASS CLASS_LIST(M_COMMA_PRE)> { \
183 using super = m::detail::VisitorImpl<VISITOR_NAME, BASE_CLASS CLASS_LIST(M_COMMA_PRE)>; \
184 using super::operator(); \
185 }; \
186 M_MAKE_STL_VISITABLE(VISITOR_NAME, BASE_CLASS, CLASS_LIST)
‍mutable namespace
Definition: Backend.hpp:10
auto visit(Callable &&callable, Base &obj, m::tag< Callable > &&=m::tag< Callable >())
Generic implementation to visit a class hierarchy, with similar syntax as std::visit.
Definition: Visitor.hpp:138
A helper class to define CRTP class hierarchies.
Definition: crtp.hpp:50
A helper class to define virtual visit methods for all classes in.
Definition: Visitor.hpp:81
typename super::template Const< T > Const
Definition: Visitor.hpp:83
Visitor base class, using CRTP.
Definition: Visitor.hpp:30
virtual ~Visitor()
Make Visitor inheritable from.
Definition: Visitor.hpp:47
virtual void operator()(base_type &obj)
Visit the object obj.
Definition: Visitor.hpp:50
static constexpr bool is_const
Whether the visited objects are const-qualified.
Definition: Visitor.hpp:34
std::conditional_t< is_const, const T, T > Const
A helper type to apply the proper const-qualification to parameters.
Definition: Visitor.hpp:44
ConcreteVisitor visitor_type
The concrete type of the visitor.
Definition: Visitor.hpp:40
Base base_type
The base class of the class hierarchy to visit.
Definition: Visitor.hpp:37
void operator()(typename Visitor::template Const< Class > &obj) override
Definition: Visitor.hpp:114
stl_visit_helper(Callable &callable, std::optional< some< ResultType > > &result)
Definition: Visitor.hpp:111
This helper class creates a single override of operator() for one subtype in a class hierarchy,...
Definition: Visitor.hpp:92
void operator()(typename Visitor::template Const< Class > &obj) override
Definition: Visitor.hpp:98
stl_visit_helper(Callable &callable, std::optional< some< ResultType > > &result)
Definition: Visitor.hpp:95
This helper class creates a single definition of virtual void operator()(...) for one subtype in a cl...
Definition: Visitor.hpp:60
virtual void operator()(Const< Class > &)
Definition: Visitor.hpp:64
typename super::template Const< T > Const
Definition: Visitor.hpp:62
A helper type to wrap some template type parameter such that it can safely be used to declare a class...
Definition: some.hpp:16
Definition: tag.hpp:8
Exception class which can be thrown to skip recursion of the subtree in pre-order visitors.
Definition: Visitor.hpp:18
Exception class which can be thrown to stop entire recursion in visitors.
Definition: Visitor.hpp:16