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