DispatchTraits.hpp
Go to the documentation of this file.
1 //
3 // Aurora C++ Library
4 // Copyright (c) 2012-2016 Jan Haller
5 //
6 // This software is provided 'as-is', without any express or implied
7 // warranty. In no event will the authors be held liable for any damages
8 // arising from the use of this software.
9 //
10 // Permission is granted to anyone to use this software for any purpose,
11 // including commercial applications, and to alter it and redistribute it
12 // freely, subject to the following restrictions:
13 //
14 // 1. The origin of this software must not be misrepresented; you must not
15 // claim that you wrote the original software. If you use this software
16 // in a product, an acknowledgment in the product documentation would be
17 // appreciated but is not required.
18 //
19 // 2. Altered source versions must be plainly marked as such, and must not be
20 // misrepresented as being the original software.
21 //
22 // 3. This notice may not be removed or altered from any source distribution.
23 //
25 
26 #ifndef AURORA_DISPATCHTRAITS_HPP
27 #define AURORA_DISPATCHTRAITS_HPP
28 
31 
33 #include <Aurora/Config.hpp>
34 
35 #include <typeindex>
36 #include <functional>
37 
38 
39 namespace aurora
40 {
41 namespace detail
42 {
43  // Type-information for dereferenced type
44  // Important: Do not const-qualify parameters, or the first overload will accept const U*
45  template <typename T>
46  std::type_index derefTypeid(T& reference)
47  {
48  return typeid(reference);
49  }
50 
51  template <typename T>
52  std::type_index derefTypeid(T* pointer)
53  {
54  return typeid(*pointer);
55  }
56 
57 } // namespace detail
58 
59 // ---------------------------------------------------------------------------------------------------------------------------
60 
61 
64 
70 template <typename K>
72 {
75  typedef K Key;
76 
79  static const Key& keyFromId(const Key& k)
80  {
81  return k;
82  }
83 
86  template <typename UnusedId, typename Fn>
87  static Fn trampoline1(Fn f)
88  {
89  return f;
90  }
91 
94  template <typename UnusedId1, typename UnusedId2, typename Fn>
95  static Fn trampoline2(Fn f)
96  {
97  return f;
98  }
99 
102  static const char* name(Key)
103  {
104  return "unknown";
105  }
106 };
107 
111 template <typename S, std::size_t N>
113 {
114  // ---------------------------------------------------------------------------------------------------------------------------
115  // Private types
116  private:
117  typedef typename FunctionResult<S>::Type R;
118  typedef typename FunctionParam<S, 0>::Type B;
119  typedef typename FunctionParam<S, N>::Type U;
120 
121  static_assert(std::is_polymorphic<typename std::remove_pointer<typename std::remove_reference<B>::type>::type>::value,
122  "B must be a pointer or reference to a polymorphic base class.");
123 
124 
125  // ---------------------------------------------------------------------------------------------------------------------------
126  // Public types and static member functions
127  public:
130  typedef std::type_index Key;
131 
134  static Key keyFromBase(B m)
135  {
136  return detail::derefTypeid(m);
137  }
138 
141  template <typename T>
142  static Key keyFromId(Type<T> id)
143  {
144  static_cast<void>(id); // unused parameter
145  return typeid(T);
146  }
147 
150  template <typename Id, typename Fn>
151  static std::function<S> trampoline1(Fn f)
152  {
153  return trampoline1<Id, Fn>(f, Int<FunctionArity<S>::value - N>());
154  }
155 
158  template <typename Id1, typename Id2, typename Fn>
159  static std::function<S> trampoline2(Fn f)
160  {
161  return trampoline2<Id1, Id2, Fn>(f, Int<FunctionArity<S>::value - N>());
162  }
163 
166  static const char* name(Key k)
167  {
168  return k.name();
169  }
170 
171 
172  // ---------------------------------------------------------------------------------------------------------------------------
173  // Private types and static member functions
174  private:
175  // Implementation for signature without additional argument
176  template <typename Id, typename Fn>
177  static std::function<S> trampoline1(Fn f, Int<0>)
178  {
179  return [f] (B arg) mutable -> R
180  {
181  typedef AURORA_REPLICATE(B, typename Id::type) Derived;
182  return f(static_cast<Derived>(arg));
183  };
184  }
185 
186  // Implementation for signature with a user-defined argument
187  template <typename Id, typename Fn>
188  static std::function<S> trampoline1(Fn f, Int<1>)
189  {
190  return [f] (B arg, U userData) mutable -> R
191  {
192  typedef AURORA_REPLICATE(B, typename Id::type) Derived;
193  return f(static_cast<Derived>(arg), userData);
194  };
195  }
196 
197  // Implementation for signature without additional argument
198  template <typename Id1, typename Id2, typename Fn>
199  static std::function<S> trampoline2(Fn f, Int<0>)
200  {
201  return [f] (B arg1, B arg2) mutable -> R
202  {
203  typedef AURORA_REPLICATE(B, typename Id1::type) Derived1;
204  typedef AURORA_REPLICATE(B, typename Id2::type) Derived2;
205  return f(static_cast<Derived1>(arg1), static_cast<Derived2>(arg2));
206  };
207  }
208 
209  // Implementation for signature with a user-defined argument
210  template <typename Id1, typename Id2, typename Fn>
211  static std::function<S> trampoline2(Fn f, Int<1>)
212  {
213  return [f] (B arg1, B arg2, U userData) mutable -> R
214  {
215  typedef AURORA_REPLICATE(B, typename Id1::type) Derived1;
216  typedef AURORA_REPLICATE(B, typename Id2::type) Derived2;
217  return f(static_cast<Derived1>(arg1), static_cast<Derived2>(arg2), userData);
218  };
219  }
220 };
221 
227 template <typename R, unsigned int N>
228 struct NoOp
229 {
230 };
231 
233 
234 template <typename R>
235 struct NoOp<R, 0>
236 {
237  R operator() () const
238  {
239  return R();
240  }
241 };
242 
243 template <typename R>
244 struct NoOp<R, 1>
245 {
246  template <typename T1>
247  R operator() (const T1&) const
248  {
249  return R();
250  }
251 };
252 
253 template <typename R>
254 struct NoOp<R, 2>
255 {
256  template <typename T1, typename T2>
257  R operator() (const T1&, const T2&) const
258  {
259  return R();
260  }
261 };
262 
263 } // namespace aurora
264 
265 #endif // AURORA_DISPATCHTRAITS_HPP
Utilities for template metaprogramming.
Functor doing nothing.
Definition: DispatchTraits.hpp:228
static Fn trampoline2(Fn f)
Maps a function to itself (no trampoline needed)
Definition: DispatchTraits.hpp:95
Simple type wrapper, can be used for overload resolution.
Definition: Templates.hpp:120
static const char * name(Key)
Returns a string representation of the key, for debugging.
Definition: DispatchTraits.hpp:102
static Key keyFromId(Type< T > id)
Function that takes static type information and returns a type-erased std::type_index object...
Definition: DispatchTraits.hpp:142
Configuration header of the library.
Simple integer wrapper, can be used for overload resolution.
Definition: Templates.hpp:128
K Key
Key to differentiate objects.
Definition: DispatchTraits.hpp:75
static Key keyFromBase(B m)
Function that takes an object to identify and returns the corresponding std::type_index object...
Definition: DispatchTraits.hpp:134
Identifies a class using RTTI.
Definition: DispatchTraits.hpp:112
static std::function< S > trampoline1(Fn f)
Wraps a function such that the argument is downcast before being passed.
Definition: DispatchTraits.hpp:151
static Fn trampoline1(Fn f)
Maps a function to itself (no trampoline needed)
Definition: DispatchTraits.hpp:87
static const Key & keyFromId(const Key &k)
Maps a key to itself (assuming key and type identifier are the same)
Definition: DispatchTraits.hpp:79
static std::function< S > trampoline2(Fn f)
Wraps a function such that both arguments are downcast before being passed.
Definition: DispatchTraits.hpp:159
std::type_index Key
Key type.
Definition: DispatchTraits.hpp:122
Helper base class to implement custom traits for dispatchers.
Definition: DispatchTraits.hpp:71
static const char * name(Key k)
Returns a string representation of the key, for debugging.
Definition: DispatchTraits.hpp:166
Definition: DispatchTraits.hpp:39