paludis Version 3.0.2
The one true package mangler
visitor.hh
1/* vim: set sw=4 sts=4 et foldmethod=syntax : */
2
3/*
4 * Copyright (c) 2008, 2009, 2010, 2011, 2013 Ciaran McCreesh
5 *
6 * This file is part of the Paludis package manager. Paludis is free software;
7 * you can redistribute it and/or modify it under the terms of the GNU General
8 * Public License version 2, as published by the Free Software Foundation.
9 *
10 * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 * details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef PALUDIS_GUARD_PALUDIS_UTIL_VISITOR_HH
21#define PALUDIS_GUARD_PALUDIS_UTIL_VISITOR_HH 1
22
24#include <paludis/util/visitor-fwd.hh>
26#include <functional>
27
28namespace paludis
29{
30 /**
31 * Used by accept_visitor.
32 *
33 * \nosubgrouping
34 * \ingroup g_visitors
35 */
36 template <typename Visitor_>
37 class PALUDIS_VISIBLE AcceptVisitor
38 {
39 private:
40 Visitor_ & _v;
41
42 public:
43 typedef void result_type;
44
45 ///\name Visitor operations
46 ///\{
47
48 AcceptVisitor(Visitor_ & v) :
49 _v(v)
50 {
51 }
52
53 template <typename T_>
54 void operator() (T_ & t) const
55 {
56 t.accept(_v);
57 }
58
59 ///\}
60 };
61
62 /**
63 * Used by accept_visitor.
64 *
65 * \nosubgrouping
66 * \ingroup g_visitors
67 */
68 template <typename Visitor_, typename Returning_>
69 class PALUDIS_VISIBLE AcceptVisitorReturning
70 {
71 private:
72 Visitor_ & _v;
73
74 public:
75 typedef Returning_ result_type;
76
77 ///\name Visitor operations
78 ///\{
79
80 AcceptVisitorReturning(Visitor_ & v) :
81 _v(v)
82 {
83 }
84
85 template <typename T_>
86 Returning_ operator() (T_ & t) const
87 {
88 return t.template accept_returning<Returning_>(_v);
89 }
90
91 ///\}
92 };
93
94 /**
95 * Convenience function for using a visitor with a standard algorithm.
96 *
97 * \ingroup g_visitors
98 */
99 template <typename Visitor_>
104
105 /**
106 * Convenience function for using a visitor with a standard algorithm.
107 *
108 * \ingroup g_visitors
109 */
110 template <typename Returning_, typename Visitor_>
115
116 template <typename>
118
119 template <typename T_, typename R_, typename A1_, typename... As_>
120 struct ExtractFirstArgumentType<R_ (T_::*) (A1_, As_...) const>
121 {
122 typedef A1_ Type;
123 };
124
125 template <typename T_>
126 using FirstCallArgumentType = typename ExtractFirstArgumentType<decltype(&T_::operator())>::Type;
127
128 template <typename>
130
131 template <typename T_, typename R_, typename... As_>
132 struct ExtractResultType<R_ (T_::*) (As_...) const>
133 {
134 typedef R_ Type;
135 };
136
137 template <typename T_>
138 using CallResultType = typename std::remove_const<typename ExtractResultType<decltype(&T_::operator())>::Type>::type;
139
140 template <typename Revisitor_, typename Result_, typename... Cases_>
142
143 template <typename Revisitor_, typename Result_>
144 struct MadeVisitor<Revisitor_, Result_>
145 {
146 Result_ visit(const NoType<0u> &) const;
147 };
148
149 template <typename>
151
152 template <typename T_, typename R_, typename A1_>
153 struct CallThisCaseNeedsTwoArgs<R_ (T_::*) (A1_) const>
154 {
155 enum { value = false };
156 };
157
158 template <typename T_, typename R_, typename A1_, typename A2_>
159 struct CallThisCaseNeedsTwoArgs<R_ (T_::*) (A1_, A2_) const>
160 {
161 enum { value = true };
162 };
163
164 template <typename Result_, typename Case_, typename V_, bool needs_two_args_>
166
167 template <typename Result_, typename Case_, typename V_>
168 struct CallThisCase<Result_, Case_, V_, false>
169 {
170 static Result_ call(const Case_ & thiscase, const FirstCallArgumentType<Case_> & v, const V_ &)
171 {
172 return thiscase(v);
173 }
174 };
175
176 template <typename Result_, typename Case_, typename V_>
177 struct CallThisCase<Result_, Case_, V_, true>
178 {
179 static Result_ call(const Case_ & thiscase, const FirstCallArgumentType<Case_> & v, const V_ & revisitor)
180 {
181 return thiscase(v, accept_visitor_returning<Result_>(revisitor));
182 }
183 };
184
185 template <typename Case_, typename V_>
186 struct CallThisCase<void, Case_, V_, true>
187 {
188 static void call(const Case_ & thiscase, const FirstCallArgumentType<Case_> & v, const V_ & revisitor)
189 {
190 thiscase(v, accept_visitor(revisitor));
191 }
192 };
193
194 template <typename Revisitor_, typename Result_, typename Case_, typename... Rest_>
195 struct MadeVisitor<Revisitor_, Result_, Case_, Rest_...> :
196 MadeVisitor<Revisitor_, Result_, Rest_...>
197 {
198 const Case_ & thiscase;
199
200 MadeVisitor(const Case_ & c, const Rest_ & ... cases) :
201 MadeVisitor<Revisitor_, Result_, Rest_...>(cases...),
202 thiscase(c)
203 {
204 }
205
206 using MadeVisitor<Revisitor_, Result_, Rest_...>::visit;
207
208 Result_ visit(const FirstCallArgumentType<Case_> & v) const
209 {
210 return CallThisCase<Result_, Case_, Revisitor_, CallThisCaseNeedsTwoArgs<decltype(&Case_::operator())>::value>::call(
211 thiscase, v, *static_cast<const Revisitor_ *>(this));
212 }
213 };
214
215 template <typename Result_, typename... Cases_>
216 struct BaseMadeVisitor :
217 MadeVisitor<BaseMadeVisitor<Result_, Cases_...>, Result_, Cases_...>
218 {
219 BaseMadeVisitor(const Cases_ & ... cases) :
220 MadeVisitor<BaseMadeVisitor<Result_, Cases_...>, Result_, Cases_...>(cases...)
221 {
222 }
223 };
224
225 template <typename Case_, typename... Cases_>
226 auto make_visitor(const Case_ & firstcase, const Cases_ & ... cases) -> BaseMadeVisitor<CallResultType<Case_>, Case_, Cases_...>
227 {
228 return BaseMadeVisitor<CallResultType<Case_>, Case_, Cases_...>{ firstcase, cases... };
229 }
230
231 template <typename Result_, typename Base_>
232 using Revisit = std::function<Result_ (const Base_ &)>;
233
234 template <>
236 {
237 public:
238 void forward_visit(const NoType<0u> &);
239 };
240
241 template <typename TypeList_>
243 public virtual DeclareAbstractVisitMethods<typename TypeList_::Tail>
244 {
245 public:
246 using DeclareAbstractVisitMethods<typename TypeList_::Tail>::forward_visit;
247
248 virtual void forward_visit(typename TypeList_::Item &) = 0;
249 };
250
251 template <typename TypeList_>
253 public virtual DeclareAbstractVisitMethods<TypeList_>
254 {
255 };
256
257 template <typename RealClass_>
259 {
260 public:
261 void forward_visit(const NoType<1u> &);
262 };
263
264 template <typename RealClass_, typename TypeList_>
266 public virtual DeclareAbstractVisitMethods<TypeList_>,
267 public ImplementVisitMethods<RealClass_, typename TypeList_::Tail>
268 {
269 public:
270 using ImplementVisitMethods<RealClass_, typename TypeList_::Tail>::forward_visit;
271
272 void forward_visit(typename TypeList_::Item & n) override
273 {
274 static_cast<RealClass_ *>(this)->perform_visit(n);
275 }
276 };
277
278 template <typename TypeList_, typename UnwrappedVisitor_>
279 class WrappedVoidResultVisitor :
280 public WrappedVisitorBase<TypeList_>,
281 public ImplementVisitMethods<WrappedVoidResultVisitor<TypeList_, UnwrappedVisitor_>, TypeList_>
282 {
283 private:
284 UnwrappedVisitor_ & _unwrapped_visitor;
285
286 public:
287 WrappedVoidResultVisitor(UnwrappedVisitor_ & v) :
288 _unwrapped_visitor(v)
289 {
290 }
291
292 template <typename C_>
293 void perform_visit(C_ & t)
294 {
295 _unwrapped_visitor.visit(t);
296 }
297 };
298
299 template <typename TypeList_, typename Result_, typename UnwrappedVisitor_>
300 class WrappedNonVoidResultVisitor :
301 public WrappedVisitorBase<TypeList_>,
302 public ImplementVisitMethods<WrappedNonVoidResultVisitor<TypeList_, Result_, UnwrappedVisitor_>,
303 TypeList_>
304 {
305 private:
306 UnwrappedVisitor_ & _unwrapped_visitor;
307
308 public:
309 Result_ result;
310
311 WrappedNonVoidResultVisitor(UnwrappedVisitor_ & v, const Result_ & r) :
312 _unwrapped_visitor(v),
313 result(r)
314 {
315 }
316
317 template <typename C_>
318 void perform_visit(C_ & t)
319 {
320 result = _unwrapped_visitor.visit(t);
321 }
322 };
323
324 template <typename BaseClass_, typename VisitableTypeList_>
326 {
327 private:
328 virtual void _real_accept(WrappedVisitorBase<VisitableTypeList_> &) = 0;
329 virtual void _real_accept_const(WrappedVisitorBase<typename MakeTypeListConst<VisitableTypeList_>::Type> &) const = 0;
330
331 public:
332 typedef VisitableTypeList_ VisitableTypeList;
333 typedef BaseClass_ VisitableBaseClass;
334
335 template <typename UnwrappedVisitor_>
336 void accept(UnwrappedVisitor_ & v)
337 {
339 _real_accept(vv);
340 }
341
342 template <typename UnwrappedVisitor_>
343 void accept(UnwrappedVisitor_ & v) const
344 {
346 _real_accept_const(vv);
347 }
348
349 template <typename UnwrappedVisitor_>
350 void accept(const UnwrappedVisitor_ & v)
351 {
353 _real_accept(vv);
354 }
355
356 template <typename UnwrappedVisitor_>
357 void accept(const UnwrappedVisitor_ & v) const
358 {
360 _real_accept_const(vv);
361 }
362
363 template <typename Result_, typename UnwrappedVisitor_>
364 Result_ accept_returning(UnwrappedVisitor_ & v, const Result_ & r = Result_())
365 {
367 _real_accept(vv);
368 return vv.result;
369 }
370
371 template <typename Result_, typename UnwrappedVisitor_>
372 Result_ accept_returning(const UnwrappedVisitor_ & v, const Result_ & r = Result_())
373 {
375 _real_accept(vv);
376 return vv.result;
377 }
378
379 template <typename Result_, typename UnwrappedVisitor_>
380 Result_ accept_returning(UnwrappedVisitor_ & v, const Result_ & r = Result_()) const
381 {
383 _real_accept_const(vv);
384 return vv.result;
385 }
386
387 template <typename Result_, typename UnwrappedVisitor_>
388 Result_ accept_returning(const UnwrappedVisitor_ & v, const Result_ & r = Result_()) const
389 {
391 _real_accept_const(vv);
392 return vv.result;
393 }
394
395 template <typename Case_, typename... Cases_>
396 auto make_accept_returning(const Case_ & firstcase, const Cases_ & ... cases) const -> CallResultType<Case_>
397 {
398 return this->accept_returning<CallResultType<Case_> >(make_visitor(firstcase, cases...));
399 }
400
401 template <typename... Cases_>
402 void make_accept(const Cases_ & ... cases) const
403 {
404 this->accept(make_visitor(cases...));
405 }
406 };
407
408 template <typename BaseClass_, typename RealClass_>
410 public virtual DeclareAbstractAcceptMethods<BaseClass_, typename BaseClass_::VisitableTypeList>
411 {
412 private:
414 {
415 v.forward_visit(*static_cast<RealClass_ *>(this));
416 };
417
418 void _real_accept_const(WrappedVisitorBase<typename MakeTypeListConst<typename BaseClass_::VisitableTypeList>::Type> & v) const override
419 {
420 v.forward_visit(*static_cast<const RealClass_ *>(this));
421 };
422 };
423}
424
425#endif
Definition visitor.hh:70
Definition visitor.hh:38
Definition visitor.hh:326
Definition visitor.hh:244
Definition visitor.hh:411
Definition visitor.hh:268
Definition no_type.hh:43
Definition visitor.hh:304
Definition visitor.hh:254
Definition visitor.hh:282
#define PALUDIS_VISIBLE
Definition attributes.hh:59
AcceptVisitorReturning< Visitor_, Returning_ > PALUDIS_VISIBLE accept_visitor_returning(Visitor_ &v)
Definition visitor.hh:111
AcceptVisitor< Visitor_ > PALUDIS_VISIBLE accept_visitor(Visitor_ &v)
Definition visitor.hh:100
Definition about_metadata-fwd.hh:24
Definition visitor.hh:218
Definition visitor.hh:150
Definition visitor.hh:165
Definition visitor.hh:117
Definition visitor.hh:129
Definition visitor.hh:141
Definition type_list.hh:28