1 /*
2 * Copyright (c) 2011-2021, The DART development contributors
3 * All rights reserved.
4 *
5 * The list of contributors can be found at:
6 * https://github.com/dartsim/dart/blob/master/LICENSE
7 *
8 * This file is provided under the following "BSD-style" License:
9 * Redistribution and use in source and binary forms, with or
10 * without modification, are permitted provided that the following
11 * conditions are met:
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifndef DART_COMMON_DETAIL_SPECIALIZEDFORASPECT_HPP_
34 #define DART_COMMON_DETAIL_SPECIALIZEDFORASPECT_HPP_
35
36 #include "dart/common/SpecializedForAspect.hpp"
37
38 // This preprocessor token should only be used by the unittest that is
39 // responsible for checking that the specialized routines are being used to
40 // access specialized Aspects
41 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
42 bool usedSpecializedAspectAccess;
43 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
44
45 namespace dart {
46 namespace common {
47
48 //==============================================================================
49 template <class SpecAspect>
SpecializedForAspect()50 SpecializedForAspect<SpecAspect>::SpecializedForAspect()
51 {
52 mSpecAspectIterator
53 = mAspectMap
54 .insert(std::make_pair<std::type_index, std::unique_ptr<Aspect>>(
55 typeid(SpecAspect), nullptr))
56 .first;
57 }
58
59 //==============================================================================
60 template <class SpecAspect>
61 template <class T>
has() const62 bool SpecializedForAspect<SpecAspect>::has() const
63 {
64 return _has(type<T>());
65 }
66
67 //==============================================================================
68 template <class SpecAspect>
69 template <class T>
get()70 T* SpecializedForAspect<SpecAspect>::get()
71 {
72 return _get(type<T>());
73 }
74
75 //==============================================================================
76 template <class SpecAspect>
77 template <class T>
get() const78 const T* SpecializedForAspect<SpecAspect>::get() const
79 {
80 return _get(type<T>());
81 }
82
83 //==============================================================================
84 template <class SpecAspect>
85 template <class T>
set(const T * aspect)86 void SpecializedForAspect<SpecAspect>::set(const T* aspect)
87 {
88 _set(type<T>(), aspect);
89 }
90
91 //==============================================================================
92 template <class SpecAspect>
93 template <class T>
set(std::unique_ptr<T> && aspect)94 void SpecializedForAspect<SpecAspect>::set(std::unique_ptr<T>&& aspect)
95 {
96 _set(type<T>(), std::move(aspect));
97 }
98
99 //==============================================================================
100 template <class SpecAspect>
101 template <class T, typename... Args>
102 T* SpecializedForAspect<SpecAspect>::createAspect(Args&&... args)
103 {
104 return _createAspect(type<T>(), std::forward<Args>(args)...);
105 }
106
107 //==============================================================================
108 template <class SpecAspect>
109 template <class T>
removeAspect()110 void SpecializedForAspect<SpecAspect>::removeAspect()
111 {
112 _removeAspect(type<T>());
113 }
114
115 //==============================================================================
116 template <class SpecAspect>
117 template <class T>
releaseAspect()118 std::unique_ptr<T> SpecializedForAspect<SpecAspect>::releaseAspect()
119 {
120 return _releaseAspect(type<T>());
121 }
122
123 //==============================================================================
124 template <class SpecAspect>
125 template <class T>
isSpecializedFor()126 constexpr bool SpecializedForAspect<SpecAspect>::isSpecializedFor()
127 {
128 return _isSpecializedFor(type<T>());
129 }
130
131 //==============================================================================
132 template <class SpecAspect>
133 template <class T>
_has(type<T>) const134 bool SpecializedForAspect<SpecAspect>::_has(type<T>) const
135 {
136 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
137 usedSpecializedAspectAccess = true;
138 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
139
140 return Composite::has<T>();
141 }
142
143 //==============================================================================
144 template <class SpecAspect>
_has(type<SpecAspect>) const145 bool SpecializedForAspect<SpecAspect>::_has(type<SpecAspect>) const
146 {
147 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
148 usedSpecializedAspectAccess = true;
149 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
150
151 return (mSpecAspectIterator->second.get() != nullptr);
152 }
153
154 //==============================================================================
155 template <class SpecAspect>
156 template <class T>
_get(type<T>)157 T* SpecializedForAspect<SpecAspect>::_get(type<T>)
158 {
159 return Composite::get<T>();
160 }
161
162 //==============================================================================
163 template <class SpecAspect>
_get(type<SpecAspect>)164 SpecAspect* SpecializedForAspect<SpecAspect>::_get(type<SpecAspect>)
165 {
166 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
167 usedSpecializedAspectAccess = true;
168 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
169
170 return static_cast<SpecAspect*>(mSpecAspectIterator->second.get());
171 }
172
173 //==============================================================================
174 template <class SpecAspect>
175 template <class T>
_get(type<T>) const176 const T* SpecializedForAspect<SpecAspect>::_get(type<T>) const
177 {
178 return Composite::get<T>();
179 }
180
181 //==============================================================================
182 template <class SpecAspect>
_get(type<SpecAspect>) const183 const SpecAspect* SpecializedForAspect<SpecAspect>::_get(type<SpecAspect>) const
184 {
185 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
186 usedSpecializedAspectAccess = true;
187 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
188
189 return static_cast<SpecAspect*>(mSpecAspectIterator->second.get());
190 }
191
192 //==============================================================================
193 template <class SpecAspect>
194 template <class T>
_set(type<T>,const T * aspect)195 void SpecializedForAspect<SpecAspect>::_set(type<T>, const T* aspect)
196 {
197 Composite::set<T>(aspect);
198 }
199
200 //==============================================================================
201 template <class SpecAspect>
_set(type<SpecAspect>,const SpecAspect * aspect)202 void SpecializedForAspect<SpecAspect>::_set(
203 type<SpecAspect>, const SpecAspect* aspect)
204 {
205 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
206 usedSpecializedAspectAccess = true;
207 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
208
209 if (aspect)
210 {
211 mSpecAspectIterator->second = aspect->cloneAspect();
212 addToComposite(mSpecAspectIterator->second.get());
213 }
214 else
215 {
216 mSpecAspectIterator->second = nullptr;
217 }
218 }
219
220 //==============================================================================
221 template <class SpecAspect>
222 template <class T>
_set(type<T>,std::unique_ptr<T> && aspect)223 void SpecializedForAspect<SpecAspect>::_set(
224 type<T>, std::unique_ptr<T>&& aspect)
225 {
226 Composite::set<T>(std::move(aspect));
227 }
228
229 //==============================================================================
230 template <class SpecAspect>
_set(type<SpecAspect>,std::unique_ptr<SpecAspect> && aspect)231 void SpecializedForAspect<SpecAspect>::_set(
232 type<SpecAspect>, std::unique_ptr<SpecAspect>&& aspect)
233 {
234 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
235 usedSpecializedAspectAccess = true;
236 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
237
238 mSpecAspectIterator->second = std::move(aspect);
239 addToComposite(mSpecAspectIterator->second.get());
240 }
241
242 //==============================================================================
243 template <class SpecAspect>
244 template <class T, typename... Args>
245 T* SpecializedForAspect<SpecAspect>::_createAspect(type<T>, Args&&... args)
246 {
247 return Composite::createAspect<T>(std::forward<Args>(args)...);
248 }
249
250 //==============================================================================
251 template <class SpecAspect>
252 template <typename... Args>
_createAspect(type<SpecAspect>,Args &&...args)253 SpecAspect* SpecializedForAspect<SpecAspect>::_createAspect(
254 type<SpecAspect>, Args&&... args)
255 {
256 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
257 usedSpecializedAspectAccess = true;
258 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
259
260 SpecAspect* aspect = new SpecAspect(std::forward<Args>(args)...);
261 mSpecAspectIterator->second = std::unique_ptr<SpecAspect>(aspect);
262 addToComposite(aspect);
263
264 return aspect;
265 }
266
267 //==============================================================================
268 template <class SpecAspect>
269 template <class T>
_removeAspect(type<T>)270 void SpecializedForAspect<SpecAspect>::_removeAspect(type<T>)
271 {
272 Composite::removeAspect<T>();
273 }
274
275 //==============================================================================
276 template <class SpecAspect>
_removeAspect(type<SpecAspect>)277 void SpecializedForAspect<SpecAspect>::_removeAspect(type<SpecAspect>)
278 {
279 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
280 usedSpecializedAspectAccess = true;
281 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
282
283 DART_COMMON_CHECK_ILLEGAL_ASPECT_ERASE(erase, SpecAspect, DART_BLANK);
284
285 removeFromComposite(mSpecAspectIterator->second.get());
286 mSpecAspectIterator->second = nullptr;
287 }
288
289 //==============================================================================
290 template <class SpecAspect>
291 template <class T>
_releaseAspect(type<T>)292 std::unique_ptr<T> SpecializedForAspect<SpecAspect>::_releaseAspect(type<T>)
293 {
294 return Composite::releaseAspect<T>();
295 }
296
297 //==============================================================================
298 template <class SpecAspect>
_releaseAspect(type<SpecAspect>)299 std::unique_ptr<SpecAspect> SpecializedForAspect<SpecAspect>::_releaseAspect(
300 type<SpecAspect>)
301 {
302 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
303 usedSpecializedAspectAccess = true;
304 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
305
306 DART_COMMON_CHECK_ILLEGAL_ASPECT_ERASE(release, SpecAspect, nullptr);
307
308 removeFromComposite(mSpecAspectIterator->second.get());
309 std::unique_ptr<SpecAspect> extraction(
310 static_cast<SpecAspect*>(mSpecAspectIterator->second.release()));
311
312 return extraction;
313 }
314
315 //==============================================================================
316 template <class SpecAspect>
317 template <class T>
_isSpecializedFor(type<T>)318 constexpr bool SpecializedForAspect<SpecAspect>::_isSpecializedFor(type<T>)
319 {
320 return false;
321 }
322
323 //==============================================================================
324 template <class SpecAspect>
_isSpecializedFor(type<SpecAspect>)325 constexpr bool SpecializedForAspect<SpecAspect>::_isSpecializedFor(
326 type<SpecAspect>)
327 {
328 return true;
329 }
330
331 } // namespace common
332 } // namespace dart
333
334 #endif // DART_COMMON_DETAIL_SPECIALIZEDFORASPECT_HPP_
335