dune-common  2.7.1
overloadset.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 #ifndef DUNE_COMMON_OVERLOADSET_HH
4 #define DUNE_COMMON_OVERLOADSET_HH
5 
6 #include <utility>
7 #include <type_traits>
8 
10 
11 
12 
13 namespace Dune {
14 
15 namespace Impl {
16 
17 #if __cpp_variadic_using >= 201611
18 
19  template<typename... F>
20  class OverloadSet
21  : public F...
22  {
23 
24  public:
25 
26  template<typename... FF>
27  OverloadSet(FF&&... ff)
28  : F(std::forward<FF>(ff))...
29  {}
30 
31  using F::operator()...;
32 
33  };
34 
35 #else // __cpp_variadic_using >= 201611
36 
37  // This overload set derives from
38  // all passed functions. Since we
39  // cannot do argument pack expansion
40  // on using statements this is done recursively.
41  template<class F0, class... F>
42  class OverloadSet: public OverloadSet<F...>, F0
43  {
44  using Base = OverloadSet<F...>;
45  public:
46 
47  template<class FF0, class... FF>
48  OverloadSet(FF0&& f0, FF&&... ff) :
49  Base(std::forward<FF>(ff)...),
50  F0(std::forward<FF0>(f0))
51  {}
52 
53  // pull in operator() of F0 and of all F... via the base class
54  using F0::operator();
55  using Base::operator();
56  };
57 
58  template<class F0>
59  class OverloadSet<F0>: public F0
60  {
61  public:
62 
63  template<class FF0>
64  OverloadSet(FF0&& f0) :
65  F0(std::forward<FF0>(f0))
66  {}
67 
68  // pull in operator() of F0
69  using F0::operator();
70  };
71 
72 #endif // __cpp_variadic_using >= 201611
73 
74 } // end namespace Impl
75 
76 
77 
108 template<class... F>
109 auto overload(F&&... f)
110 {
111  return Impl::OverloadSet<std::decay_t<F>...>(std::forward<F>(f)...);
112 }
113 
114 
115 
116 namespace Impl {
117 
118  template<class F0, class... F>
119  class OrderedOverloadSet: public OrderedOverloadSet<F...>, F0
120  {
121  using Base = OrderedOverloadSet<F...>;
122  public:
123 
124  template<class FF0, class... FF>
125  OrderedOverloadSet(FF0&& f0, FF&&... ff) :
126  Base(std::forward<FF>(ff)...),
127  F0(std::forward<FF0>(f0))
128  {}
129 
130  // Forward to operator() of F0 if it can be called with the given arguments.
131  template<class... Args,
132  std::enable_if_t<Std::is_callable<F0(Args&&...)>::value, int> = 0>
133  decltype(auto) operator()(Args&&... args)
134  {
135  return F0::operator()(std::forward<Args>(args)...);
136  }
137 
138  // Forward to operator() of base class if F0 cannot be called with the given
139  // arguments. In this case the base class will successively try operator()
140  // of all F... .
141  template<class... Args,
142  std::enable_if_t< not Std::is_callable<F0(Args&&...)>::value, int> = 0>
143  decltype(auto) operator()(Args&&... args)
144  {
145  return Base::operator()(std::forward<Args>(args)...);
146  }
147 
148  };
149 
150  template<class F0>
151  class OrderedOverloadSet<F0>: public F0
152  {
153  public:
154 
155  template<class FF0>
156  OrderedOverloadSet(FF0&& f0) :
157  F0(std::forward<FF0>(f0))
158  {}
159 
160  // Forward to operator() of F0. If it cannot be called with
161  // the given arguments a static assertion will fail.
162  template<class... Args>
163  decltype(auto) operator()(Args&&... args)
164  {
165  static_assert(Std::is_callable<F0(Args&&...)>::value, "No matching overload found in OrderedOverloadSet");
166  return F0::operator()(std::forward<Args>(args)...);
167  }
168  };
169 
170 } // end namespace Impl
171 
172 
173 
202 template<class... F>
203 auto orderedOverload(F&&... f)
204 {
205  return Impl::OrderedOverloadSet<std::decay_t<F>...>(std::forward<F>(f)...);
206 }
207 
208 
209 
210 } // end namespace Dune
211 
212 #endif // DUNE_COMMON_OVERLOADSET_HH
auto orderedOverload(F &&... f)
Create an ordered overload set.
Definition: overloadset.hh:203
auto overload(F &&... f)
Create an overload set.
Definition: overloadset.hh:109
Dune namespace.
Definition: alignedallocator.hh:14