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_SPECIALIZEDFORASPECT_HPP_
34 #define DART_COMMON_SPECIALIZEDFORASPECT_HPP_
35 
36 #include "dart/common/Composite.hpp"
37 #include "dart/common/CompositeJoiner.hpp"
38 #include "dart/common/Virtual.hpp"
39 
40 namespace dart {
41 namespace common {
42 
43 /// Declaration of the variadic template
44 template <class... OtherSpecAspects>
45 class SpecializedForAspect
46 {
47 public:
48   virtual ~SpecializedForAspect() = default;
49 };
50 
51 //==============================================================================
52 /// SpecializedForAspect allows classes that inherit Composite to have
53 /// constant-time access to a specific type of Aspect
54 DART_DECLARE_CLASS_WITH_VIRTUAL_BASE_BEGIN
55 
56 template <class SpecAspect>
57 class SpecializedForAspect<SpecAspect> : public virtual Composite
58 {
59 public:
60   /// Default Constructor
61   SpecializedForAspect();
62 
63   virtual ~SpecializedForAspect() = default;
64 
65   /// Check if this Composite currently has a certain type of Aspect
66   template <class T>
67   bool has() const;
68 
69   /// Get a certain type of Aspect from this Composite
70   template <class T>
71   T* get();
72 
73   /// Get a certain type of Aspect from this Composite
74   template <class T>
75   const T* get() const;
76 
77   /// Make a clone of the aspect and place the clone into this Composite. If
78   /// an Aspect of the same type already exists in this Composite, the
79   /// existing Aspect will be destroyed.
80   template <class T>
81   void set(const T* aspect);
82 
83   /// Use move semantics to place an aspect into this Composite. If an Aspect
84   /// of the same type already exists in this Composite, the existing Aspect
85   /// will be destroyed.
86   template <class T>
87   void set(std::unique_ptr<T>&& aspect);
88 
89   /// Construct an Aspect inside of this Composite
90   template <class T, typename... Args>
91   T* createAspect(Args&&... args);
92 
93   /// Remove an Aspect from this Composite
94   template <class T>
95   void removeAspect();
96 
97   /// Remove an Aspect from this Composite, but return its unique_ptr instead
98   /// of letting it be deleted. This allows you to safely use move semantics to
99   /// transfer an Aspect between two Composites.
100   template <class T>
101   std::unique_ptr<T> releaseAspect();
102 
103   /// Check if this Composite is specialized for a specific type of Aspect
104   template <class T>
105   static constexpr bool isSpecializedFor();
106 
107 protected:
108   template <class T>
109   struct type
110   {
111   };
112 
113   /// Redirect to Composite::has()
114   template <class T>
115   bool _has(type<T>) const;
116 
117   /// Specialized implementation of has()
118   bool _has(type<SpecAspect>) const;
119 
120   /// Redirect to Composite::get()
121   template <class T>
122   T* _get(type<T>);
123 
124   /// Specialized implementation of get()
125   SpecAspect* _get(type<SpecAspect>);
126 
127   /// Redirect to Composite::get()
128   template <class T>
129   const T* _get(type<T>) const;
130 
131   /// Specialized implementation of get()
132   const SpecAspect* _get(type<SpecAspect>) const;
133 
134   /// Redirect to Composite::set()
135   ///
136   /// Using the type<T> tag for this is not be necessary, but it helps to avoid
137   /// confusion between the set() versus _set() function.
138   template <class T>
139   void _set(type<T>, const T* aspect);
140 
141   /// Specialized implementation of set()
142   void _set(type<SpecAspect>, const SpecAspect* aspect);
143 
144   /// Redirect to Composite::set()
145   ///
146   /// Using the type<T> tag for this is not be necessary, but it helps to avoid
147   /// confusion between the set() versus _set() function.
148   template <class T>
149   void _set(type<T>, std::unique_ptr<T>&& aspect);
150 
151   /// Specialized implementation of set()
152   void _set(type<SpecAspect>, std::unique_ptr<SpecAspect>&& aspect);
153 
154   /// Redirect to Composite::create()
155   template <class T, typename... Args>
156   T* _createAspect(type<T>, Args&&... args);
157 
158   /// Specialized implementation of create()
159   template <typename... Args>
160   SpecAspect* _createAspect(type<SpecAspect>, Args&&... args);
161 
162   /// Redirect to Composite::erase()
163   template <class T>
164   void _removeAspect(type<T>);
165 
166   /// Specialized implementation of erase()
167   void _removeAspect(type<SpecAspect>);
168 
169   /// Redirect to Composite::release()
170   template <class T>
171   std::unique_ptr<T> _releaseAspect(type<T>);
172 
173   /// Specialized implementation of release()
174   std::unique_ptr<SpecAspect> _releaseAspect(type<SpecAspect>);
175 
176   /// Return false
177   template <class T>
178   static constexpr bool _isSpecializedFor(type<T>);
179 
180   /// Return true
181   static constexpr bool _isSpecializedFor(type<SpecAspect>);
182 
183   /// Iterator that points to the Aspect of this SpecializedForAspect
184   Composite::AspectMap::iterator mSpecAspectIterator;
185 };
186 DART_DECLARE_CLASS_WITH_VIRTUAL_BASE_END
187 
188 //==============================================================================
189 /// This is the variadic version of the SpecializedForAspect class which
190 /// allows you to include arbitrarily many specialized types in the
191 /// specialization.
192 template <class SpecAspect1, class... OtherSpecAspects>
193 class SpecializedForAspect<SpecAspect1, OtherSpecAspects...>
194   : public CompositeJoiner<
195         Virtual<SpecializedForAspect<SpecAspect1> >,
196         Virtual<SpecializedForAspect<OtherSpecAspects...> > >
197 {
198 public:
199   virtual ~SpecializedForAspect() = default;
200 };
201 
202 } // namespace common
203 } // namespace dart
204 
205 #include "dart/common/detail/SpecializedForAspect.hpp"
206 
207 #endif // DART_COMMON_SPECIALIZEDFORASPECT_HPP_
208