dune-common  2.5.0
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  // This overload set derives from
18  // all passed functions. Since we
19  // cannot do argument pack expansion
20  // on using statements this is done recursively.
21  template<class F0, class... F>
22  class OverloadSet: public OverloadSet<F...>, F0
23  {
24  using Base = OverloadSet<F...>;
25  public:
26 
27  template<class FF0, class... FF>
28  OverloadSet(FF0&& f0, FF&&... ff) :
29  Base(std::forward<FF>(ff)...),
30  F0(std::forward<FF0>(f0))
31  {}
32 
33  // pull in operator() of F0 and of all F... via the base class
34  using F0::operator();
35  using Base::operator();
36  };
37 
38  template<class F0>
39  class OverloadSet<F0>: public F0
40  {
41  public:
42 
43  template<class FF0>
44  OverloadSet(FF0&& f0) :
45  F0(std::forward<FF0>(f0))
46  {}
47 
48  // pull in operator() of F0
49  using F0::operator();
50  };
51 
52 } // end namespace Impl
53 
54 
55 
78 template<class... F>
79 auto overload(F&&... f)
80 {
81  return Impl::OverloadSet<std::decay_t<F>...>(std::forward<F>(f)...);
82 }
83 
84 
85 
86 namespace Impl {
87 
88  template<class F0, class... F>
89  class OrderedOverloadSet: public OrderedOverloadSet<F...>, F0
90  {
91  using Base = OrderedOverloadSet<F...>;
92  public:
93 
94  template<class FF0, class... FF>
95  OrderedOverloadSet(FF0&& f0, FF&&... ff) :
96  Base(std::forward<FF>(ff)...),
97  F0(std::forward<FF0>(f0))
98  {}
99 
100  // Forward to operator() of F0 if it can be called with the given arguments.
101  template<class... Args,
102  std::enable_if_t<Std::is_callable<F0(Args&&...)>::value, int> = 0>
103  decltype(auto) operator()(Args&&... args)
104  {
105  return F0::operator()(std::forward<Args>(args)...);
106  }
107 
108  // Forward to operator() of base class if F0 cannot be called with the given
109  // arguments. In this case the base class will successively try operator()
110  // of all F... .
111  template<class... Args,
112  std::enable_if_t< not Std::is_callable<F0(Args&&...)>::value, int> = 0>
113  decltype(auto) operator()(Args&&... args)
114  {
115  return Base::operator()(std::forward<Args>(args)...);
116  }
117 
118  };
119 
120  template<class F0>
121  class OrderedOverloadSet<F0>: public F0
122  {
123  public:
124 
125  template<class FF0>
126  OrderedOverloadSet(FF0&& f0) :
127  F0(std::forward<FF0>(f0))
128  {}
129 
130  // Forward to operator() of F0. If it cannot be called with
131  // the given arguments a static assertion will fail.
132  template<class... Args>
133  decltype(auto) operator()(Args&&... args)
134  {
135  static_assert(Std::is_callable<F0(Args&&...)>::value, "No matching overload found in OrderedOverloadSet");
136  return F0::operator()(std::forward<Args>(args)...);
137  }
138  };
139 
140 } // end namespace Impl
141 
142 
143 
164 template<class... F>
165 auto orderedOverload(F&&... f)
166 {
167  return Impl::OrderedOverloadSet<std::decay_t<F>...>(std::forward<F>(f)...);
168 }
169 
170 
171 
172 } // end namespace Dune
173 
174 #endif // DUNE_COMMON_OVERLOADSET_HH
OverloadSet(FF0 &&f0, FF &&... ff)
Definition: overloadset.hh:28
STL namespace.
auto orderedOverload(F &&... f)
Create an ordered overload set.
Definition: overloadset.hh:165
Definition: overloadset.hh:22
Dune namespace.
Definition: alignment.hh:10
Definition: overloadset.hh:89
Traits class to check if function is callable.
Definition: type_traits.hh:149
OrderedOverloadSet(FF0 &&f0)
Definition: overloadset.hh:126
OverloadSet(FF0 &&f0)
Definition: overloadset.hh:44
OrderedOverloadSet(FF0 &&f0, FF &&... ff)
Definition: overloadset.hh:95
auto overload(F &&... f)
Create an overload set.
Definition: overloadset.hh:79