dune-common  2.6-git
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 
102 template<class... F>
103 auto overload(F&&... f)
104 {
105  return Impl::OverloadSet<std::decay_t<F>...>(std::forward<F>(f)...);
106 }
107 
108 
109 
110 namespace Impl {
111 
112  template<class F0, class... F>
113  class OrderedOverloadSet: public OrderedOverloadSet<F...>, F0
114  {
115  using Base = OrderedOverloadSet<F...>;
116  public:
117 
118  template<class FF0, class... FF>
119  OrderedOverloadSet(FF0&& f0, FF&&... ff) :
120  Base(std::forward<FF>(ff)...),
121  F0(std::forward<FF0>(f0))
122  {}
123 
124  // Forward to operator() of F0 if it can be called with the given arguments.
125  template<class... Args,
126  std::enable_if_t<Std::is_callable<F0(Args&&...)>::value, int> = 0>
127  decltype(auto) operator()(Args&&... args)
128  {
129  return F0::operator()(std::forward<Args>(args)...);
130  }
131 
132  // Forward to operator() of base class if F0 cannot be called with the given
133  // arguments. In this case the base class will successively try operator()
134  // of all F... .
135  template<class... Args,
136  std::enable_if_t< not Std::is_callable<F0(Args&&...)>::value, int> = 0>
137  decltype(auto) operator()(Args&&... args)
138  {
139  return Base::operator()(std::forward<Args>(args)...);
140  }
141 
142  };
143 
144  template<class F0>
145  class OrderedOverloadSet<F0>: public F0
146  {
147  public:
148 
149  template<class FF0>
150  OrderedOverloadSet(FF0&& f0) :
151  F0(std::forward<FF0>(f0))
152  {}
153 
154  // Forward to operator() of F0. If it cannot be called with
155  // the given arguments a static assertion will fail.
156  template<class... Args>
157  decltype(auto) operator()(Args&&... args)
158  {
159  static_assert(Std::is_callable<F0(Args&&...)>::value, "No matching overload found in OrderedOverloadSet");
160  return F0::operator()(std::forward<Args>(args)...);
161  }
162  };
163 
164 } // end namespace Impl
165 
166 
167 
190 template<class... F>
191 auto orderedOverload(F&&... f)
192 {
193  return Impl::OrderedOverloadSet<std::decay_t<F>...>(std::forward<F>(f)...);
194 }
195 
196 
197 
198 } // end namespace Dune
199 
200 #endif // DUNE_COMMON_OVERLOADSET_HH
Dune namespace.
Definition: alignedallocator.hh:9
auto orderedOverload(F &&... f)
Create an ordered overload set.
Definition: overloadset.hh:191
auto overload(F &&... f)
Create an overload set.
Definition: overloadset.hh:103
STL namespace.
Traits class to check if function is callable.
Definition: type_traits.hh:171