LeechCraft  0.6.70-16373-g319c272718
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 "void.h"
13 #include "util.h"
14 
15 namespace LC
16 {
17 namespace Util
18 {
19  namespace detail
20  {
21  template<typename... Bases>
22  struct VisitorBase : std::decay_t<Bases>...
23  {
24  VisitorBase (Bases&&... bases)
25  : std::decay_t<Bases> { std::forward<Bases> (bases) }...
26  {
27  }
28 
29  using std::decay_t<Bases>::operator()...;
30  };
31 
32  template<class... Ts> struct Overloaded : Ts...
33  {
34  using Ts::operator()...;
35  };
36  template<class... Ts> Overloaded (Ts...) -> Overloaded<Ts...>;
37  }
38 
39  template<typename... Vars, typename... Args>
40  decltype (auto) Visit (const std::variant<Vars...>& v, Args&&... args)
41  {
42  return std::visit (detail::Overloaded { std::forward<Args> (args)... }, v);
43  }
44 
45  template<typename... Vars, typename... Args>
46  decltype (auto) Visit (std::variant<Vars...>& v, Args&&... args)
47  {
48  return std::visit (detail::Overloaded { std::forward<Args> (args)... }, v);
49  }
50 
51  template<typename... Vars, typename... Args>
52  decltype (auto) Visit (std::variant<Vars...>&& v, Args&&... args)
53  {
54  return std::visit (detail::Overloaded { std::forward<Args> (args)... }, std::move (v));
55  }
56 
57  namespace detail
58  {
59  struct VisitorFinallyTag {};
60  }
61 
62  template<typename FinallyFunc, typename... Args>
63  class Visitor
64  {
65  detail::VisitorBase<Args...> Base_;
66 
67  FinallyFunc Finally_;
68  public:
69  Visitor (Args&&... args)
70  : Base_ { std::forward<Args> (args)... }
71  {
72  }
73 
74  Visitor (detail::VisitorFinallyTag, Args&&... args, FinallyFunc&& func)
75  : Base_ { std::forward<Args> (args)... }
76  , Finally_ { std::forward<FinallyFunc> (func) }
77  {
78  }
79 
80  template<typename T>
81  decltype (auto) operator() (const T& var) const
82  {
83  if constexpr (std::is_same_v<FinallyFunc, Void>)
84  return Visit (var, Base_);
85  else
86  {
87  const auto guard = MakeScopeGuard (Finally_);
88  return Visit (var, Base_);
89  }
90  }
91 
92  template<typename F>
93  Visitor<F, detail::VisitorBase<Args...>> Finally (F&& func)
94  {
95  return { detail::VisitorFinallyTag {}, std::move (Base_), std::forward<F> (func) };
96  }
97  };
98 
99  template<typename... Args>
100  Visitor (Args&&...) -> Visitor<Void, Args...>;
101 
102  template<typename T, typename... Args>
103  auto InvokeOn (T&& t, Args&&... args)
104  {
105  return detail::VisitorBase<Args...> { std::forward<Args> (args)... } (std::forward<T> (t));
106  }
107 }
108 }
Visitor< F, detail::VisitorBase< Args... > > Finally(F &&func)
Definition: visitor.h:93
Overloaded(Ts...) -> Overloaded< Ts... >
STL namespace.
Visitor(Args &&... args)
Definition: visitor.h:69
auto Visit(const Either< Left, Right > &either, Args &&... args)
Definition: either.h:215
auto InvokeOn(T &&t, Args &&... args)
Definition: visitor.h:103
Visitor(detail::VisitorFinallyTag, Args &&... args, FinallyFunc &&func)
Definition: visitor.h:74
VisitorBase(Bases &&... bases)
Definition: visitor.h:24
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... >