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_COMPOSITE_HPP_ 34 #define DART_COMMON_COMPOSITE_HPP_ 35 36 #include "dart/common/ClassWithVirtualBase.hpp" 37 #include "dart/common/detail/CompositeData.hpp" 38 39 namespace dart { 40 namespace common { 41 42 /// Composite is a base class that should be virtually inherited by any class 43 /// that wants to be able to manage Aspects. 44 /// 45 /// The base Composite class is completely agnostic to what kind of Aspects it 46 /// is given. Aspects are stored in a std::map, so access to its Aspects happens 47 /// on average in log(N) time. Most often, a class that accepts Aspects will 48 /// have certain Aspect types that it will need to access frequently, and it 49 /// would be beneficial to have constant-time access to those Aspect types. To 50 /// get constant-time access to specific Aspect types, you can use the templated 51 /// class SpecializedForAspect. 52 class Composite 53 { 54 public: 55 using State = detail::CompositeState; 56 using Properties = detail::CompositeProperties; 57 58 using AspectMap = std::map<std::type_index, std::unique_ptr<Aspect> >; 59 using RequiredAspectSet = std::unordered_set<std::type_index>; 60 61 template <typename... Aspects> 62 using MakeState = detail::MakeCompositeState<Aspects...>; 63 64 template <typename... Aspects> 65 using MakeProperties = detail::MakeCompositeProperties<Aspects...>; 66 67 /// Virtual destructor 68 virtual ~Composite() = default; 69 70 /// Default constructor 71 Composite() = default; 72 73 /// It is currently unsafe to copy an Composite 74 // TODO(MXG): Consider making this safe by cloning Aspects into the new copy 75 Composite(const Composite&) = delete; 76 77 /// It is currently unsafe to move an Composite 78 Composite(Composite&&) = delete; 79 80 /// It is currently unsafe to copy an Composite 81 Composite& operator=(const Composite&) = delete; 82 83 /// It is currently unsafe to move an Composite 84 Composite& operator=(Composite&&) = delete; 85 86 /// Check if this Composite currently has a certain type of Aspect 87 template <class T> 88 bool has() const; 89 90 /// Get a certain type of Aspect from this Composite 91 template <class T> 92 T* get(); 93 94 /// Get a certain type of Aspect from this Composite 95 template <class T> 96 const T* get() const; 97 98 /// Make a clone of the aspect and place the clone into this Composite. If 99 /// an Aspect of the same type already exists in this Composite, the 100 /// existing Aspect will be destroyed. 101 template <class T> 102 void set(const T* aspect); 103 104 /// Use move semantics to place aspect into this Composite. If an Aspect of 105 /// the same type already exists in this Composite, the existing Aspect will 106 /// be destroyed. 107 template <class T> 108 void set(std::unique_ptr<T>&& aspect); 109 110 /// Construct an Aspect inside of this Composite 111 template <class T, typename... Args> 112 T* createAspect(Args&&... args); 113 114 /// Remove an Aspect from this Composite. 115 template <class T> 116 void removeAspect(); 117 118 /// Remove an Aspect from this Composite, but return its unique_ptr instead 119 /// of letting it be deleted. This allows you to safely use move semantics to 120 /// transfer an Aspect between two Composites. 121 template <class T> 122 std::unique_ptr<T> releaseAspect(); 123 124 /// Check if this Composite is specialized for a specific type of Aspect. 125 /// 126 /// By default, this simply returns false. 127 template <class T> 128 static constexpr bool isSpecializedFor(); 129 130 /// Check if this Composite requires this specific type of Aspect 131 template <class T> 132 bool requiresAspect() const; 133 134 /// Set the states of the aspects in this Composite based on the given 135 /// Composite::State. The states of any Aspect types that do not exist 136 /// within this composite will be ignored. 137 void setCompositeState(const State& newStates); 138 139 /// Get the states of the aspects inside of this Composite 140 State getCompositeState() const; 141 142 /// Fill outgoingStates with the states of the aspects inside this Composite 143 void copyCompositeStateTo(State& outgoingStates) const; 144 145 /// Set the properties of the aspects in this Composite based on the given 146 /// Composite::Properties. The properties of any Aspect types that do not 147 /// exist within this composite will be ignored. 148 void setCompositeProperties(const Properties& newProperties); 149 150 /// Get the properties of the aspects inside of this Composite 151 Properties getCompositeProperties() const; 152 153 /// Fill outgoingProperties with the properties of the aspects inside this 154 /// Composite 155 void copyCompositePropertiesTo(Properties& outgoingProperties) const; 156 157 /// Give this Composite a copy of each Aspect from otherComposite 158 void duplicateAspects(const Composite* fromComposite); 159 160 /// Make the Aspects of this Composite match the Aspects of otherComposite. 161 /// Any Aspects in this Composite which do not exist in otherComposite will be 162 /// erased. 163 void matchAspects(const Composite* otherComposite); 164 165 protected: 166 /// Add this Aspect to the Composite. This allows derived Composite types to 167 /// call the protected Aspect::setComposite function. 168 void addToComposite(Aspect* aspect); 169 170 /// Remove this Aspect from the Composite. This allows derived Composite types 171 /// to call the protected Aspect::loseComposite function. 172 void removeFromComposite(Aspect* aspect); 173 174 /// Non-templated version of set(const T*) 175 void _set(std::type_index type_idx, const Aspect* aspect); 176 177 /// Non-templated version of set(std::unqiue_ptr<T>&&) 178 void _set(std::type_index type_idx, std::unique_ptr<Aspect> aspect); 179 180 /// A map that relates the type of Aspect to its pointer 181 AspectMap mAspectMap; 182 183 /// A set containing type information for Aspects which are not allowed to 184 /// leave this composite. 185 RequiredAspectSet mRequiredAspects; 186 }; 187 188 //============================================================================== 189 /// Attach an arbitrary number of Aspects to the specified Composite type. 190 // TODO(MXG): Consider putting this functionality into the Composite class 191 // itself. Also consider allowing the user to specify arguments for the 192 // constructors of the Aspects. 193 template <class T> 194 void createAspects(T* /*comp*/); 195 196 //============================================================================== 197 template <class T, class NextAspect, class... Aspects> 198 void createAspects(T* comp); 199 200 } // namespace common 201 } // namespace dart 202 203 #include "dart/common/detail/Composite.hpp" 204 205 #endif // DART_COMMON_COMPOSITE_HPP_ 206