LeechCraft  0.6.70-18450-gabe19ee3b0
Modular cross-platform feature rich live environment.
visitor.h
Go to the documentation of this file.
1 /**********************************************************************
2  * LeechCraft - modular cross-platform feature rich internet client.
3  * Copyright (C) 2006-2014 Georg Rudoy
4  *
5  * Distributed under the Boost Software License, Version 1.0.
6  * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7  **********************************************************************/
8 
9 #pragma once
10 
11 #include <variant>
12 #include "overloaded.h"
13 #include "util.h"
14 #include "void.h"
15 
16 namespace LC
17 {
18 namespace Util
19 {
20  namespace detail
21  {
22  template<typename... Bases>
23  struct VisitorBase : std::decay_t<Bases>...
24  {
25  VisitorBase (Bases&&... bases)
26  : std::decay_t<Bases> { std::forward<Bases> (bases) }...
27  {
28  }
29 
30  using std::decay_t<Bases>::operator()...;
31  };
32  }
33 
34  template<typename... Vars, typename... Args>
35  decltype (auto) Visit (const std::variant<Vars...>& v, Args&&... args)
36  {
37  return std::visit (Overloaded { std::forward<Args> (args)... }, v);
38  }
39 
40  template<typename... Vars, typename... Args>
41  decltype (auto) Visit (std::variant<Vars...>& v, Args&&... args)
42  {
43  return std::visit (Overloaded { std::forward<Args> (args)... }, v);
44  }
45 
46  template<typename... Vars, typename... Args>
47  decltype (auto) Visit (std::variant<Vars...>&& v, Args&&... args)
48  {
49  return std::visit (Overloaded { std::forward<Args> (args)... }, std::move (v));
50  }
51 
52  namespace detail
53  {
54  struct VisitorFinallyTag {};
55  }
56 
57  template<typename FinallyFunc, typename... Args>
58  class Visitor
59  {
60  detail::VisitorBase<Args...> Base_;
61 
62  FinallyFunc Finally_;
63  public:
64  Visitor (Args&&... args)
65  : Base_ { std::forward<Args> (args)... }
66  {
67  }
68 
69  Visitor (detail::VisitorFinallyTag, Args&&... args, FinallyFunc&& func)
70  : Base_ { std::forward<Args> (args)... }
71  , Finally_ { std::forward<FinallyFunc> (func) }
72  {
73  }
74 
75  template<typename T>
76  decltype (auto) operator() (const T& var) const
77  {
78  if constexpr (std::is_same_v<FinallyFunc, Void>)
79  return Visit (var, Base_);
80  else
81  {
82  const auto guard = MakeScopeGuard (Finally_);
83  return Visit (var, Base_);
84  }
85  }
86 
87  template<typename F>
88  Visitor<F, detail::VisitorBase<Args...>> Finally (F&& func)
89  {
90  return { detail::VisitorFinallyTag {}, std::move (Base_), std::forward<F> (func) };
91  }
92  };
93 
94  template<typename... Args>
95  Visitor (Args&&...) -> Visitor<Void, Args...>;
96 
97  template<typename T, typename... Args>
98  auto InvokeOn (T&& t, Args&&... args)
99  {
100  return detail::VisitorBase<Args...> { std::forward<Args> (args)... } (std::forward<T> (t));
101  }
102 }
103 }
Visitor< F, detail::VisitorBase< Args... > > Finally(F &&func)
Definition: visitor.h:88
STL namespace.
Visitor(Args &&... args)
Definition: visitor.h:64
auto Visit(const Either< Left, Right > &either, Args &&... args)
Definition: either.h:180
auto InvokeOn(T &&t, Args &&... args)
Definition: visitor.h:98
Visitor(detail::VisitorFinallyTag, Args &&... args, FinallyFunc &&func)
Definition: visitor.h:69
VisitorBase(Bases &&... bases)
Definition: visitor.h:25
detail::ScopeGuard< F > MakeScopeGuard(const F &f)
Returns an object performing passed function on scope exit.
Definition: util.h:155
Visitor(Args &&...) -> Visitor< Void, Args... >