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_EMBEDDEDASPECT_HPP_ 34 #define DART_COMMON_EMBEDDEDASPECT_HPP_ 35 36 #include "dart/common/CompositeJoiner.hpp" 37 #include "dart/common/RequiresAspect.hpp" 38 #include "dart/common/detail/EmbeddedAspect.hpp" 39 40 namespace dart { 41 namespace common { 42 43 //============================================================================== 44 /// This is the implementation of a standard embedded-state Aspect. Inherit 45 /// the EmbedState class (next class down in the header) to use this Aspect 46 /// implementation. 47 /// 48 /// For more control over how your embedded-state Aspect is implemented, you can 49 /// use the detail::EmbeddedStateAspect class. 50 template <class CompositeT, typename StateDataT> 51 class EmbeddedStateAspect : public detail::EmbeddedStateAspect< 52 CompositeTrackingAspect<CompositeT>, 53 EmbeddedStateAspect<CompositeT, StateDataT>, 54 StateDataT> 55 { 56 public: 57 using Base = CompositeTrackingAspect<CompositeT>; 58 using Derived = EmbeddedStateAspect<CompositeT, StateDataT>; 59 using Impl = detail::EmbeddedStateAspect<Base, Derived, StateDataT>; 60 using State = typename Impl::State; 61 using StateData = typename Impl::StateData; 62 63 template <typename... Args> EmbeddedStateAspect(Args &&...args)64 EmbeddedStateAspect(Args&&... args) : Impl(std::forward<Args>(args)...) 65 { 66 // Do nothing 67 } 68 69 virtual ~EmbeddedStateAspect() = default; 70 }; 71 72 //============================================================================== 73 /// Inherit this class to embed a State into your Composite object. DerivedT is 74 /// the name of your class and StateDataT is a "plain-old data" structure that 75 /// holds your state information. 76 /// 77 /// Your derived class must implement the following functions: 78 /// 79 /// \code{.cpp} 80 /// void setAspectState(const AspectState& state); 81 /// \endcode 82 /// 83 /// To embed both state and properties information, use EmbedStateAndProperties. 84 /// 85 /// It is possible to customize the way an EmbeddedStateAspect interacts with 86 /// your Composite by using the dart::common::detail::EmbeddedStateAspect class 87 /// directly instead of inheriting this class. 88 DART_DECLARE_CLASS_WITH_VIRTUAL_BASE_BEGIN 89 90 template <class DerivedT, typename StateDataT> 91 class EmbedState : public virtual common::RequiresAspect< 92 common::EmbeddedStateAspect<DerivedT, StateDataT> > 93 { 94 public: 95 using Derived = DerivedT; 96 using Aspect = common::EmbeddedStateAspect<Derived, StateDataT>; 97 using AspectState = typename Aspect::State; 98 using AspectStateData = typename Aspect::StateData; 99 using Base = common::RequiresAspect<Aspect>; 100 101 // Forwarding constructor 102 template <typename... Args> EmbedState(Args &&...args)103 EmbedState(Args&&... args) : Base(std::forward<Args>(args)...) 104 { 105 // Do nothing 106 } 107 108 virtual ~EmbedState() = default; 109 getAspectState() const110 const AspectState& getAspectState() const 111 { 112 return mAspectState; 113 } 114 115 protected: 116 /// Aspect::State data, directly accessible to your derived class 117 AspectState mAspectState; 118 }; 119 DART_DECLARE_CLASS_WITH_VIRTUAL_BASE_END 120 121 //============================================================================== 122 /// This is an alternative to EmbedState which allows your class to also inherit 123 /// other Composite objects by listing them as the third (and later) template 124 /// arguments. 125 template <class DerivedT, typename StateDataT, typename... BaseComposites> 126 class EmbedStateOnTopOf 127 : public CompositeJoiner<EmbedState<DerivedT, StateDataT>, BaseComposites...> 128 { 129 public: 130 using Impl = EmbedState<DerivedT, StateDataT>; 131 using Derived = typename Impl::Derived; 132 using AspectStateData = typename Impl::AspectStateData; 133 using AspectState = typename Impl::AspectState; 134 using Aspect = typename Impl::Aspect; 135 using Base = CompositeJoiner<Impl, BaseComposites...>; 136 using Impl::getAspectState; 137 138 // Forwarding constructor 139 template <typename... Args> EmbedStateOnTopOf(Args &&...args)140 EmbedStateOnTopOf(Args&&... args) : Base(NoArg, std::forward<Args>(args)...) 141 { 142 // Do nothing 143 } 144 145 virtual ~EmbedStateOnTopOf() = default; 146 147 protected: 148 using Impl::mAspectState; 149 }; 150 151 //============================================================================== 152 /// This is the implementation of a standard embedded-properties Aspect. Inherit 153 /// the EmbedProperties (next class down in the header) to use this Aspect 154 /// implementation. 155 /// 156 /// For more control over how your embedded-properties Aspect is implemented, 157 /// you can use the detail::EmbeddedPropertiesAspect class. 158 template <class CompositeT, typename PropertiesDataT> 159 class EmbeddedPropertiesAspect 160 : public detail::EmbeddedPropertiesAspect< 161 CompositeTrackingAspect<CompositeT>, 162 EmbeddedPropertiesAspect<CompositeT, PropertiesDataT>, 163 PropertiesDataT> 164 { 165 public: 166 using Base = CompositeTrackingAspect<CompositeT>; 167 using Derived = EmbeddedPropertiesAspect<CompositeT, PropertiesDataT>; 168 using Impl = detail::EmbeddedPropertiesAspect<Base, Derived, PropertiesDataT>; 169 using Properties = typename Impl::Properties; 170 using PropertiesData = typename Impl::PropertiesData; 171 172 // Forwarding constructor 173 template <typename... Args> EmbeddedPropertiesAspect(Args &&...args)174 EmbeddedPropertiesAspect(Args&&... args) : Impl(std::forward<Args>(args)...) 175 { 176 // Do nothing 177 } 178 179 virtual ~EmbeddedPropertiesAspect() = default; 180 }; 181 182 //============================================================================== 183 /// Inherit this class to embed Properties into your Composite object. DerivedT 184 /// is the name of your class and PropertiesDataT is a "plain-old data" 185 /// structure that holds your properties information. 186 /// 187 /// Your derived class must implement the following function: 188 /// 189 /// \code{.cpp} 190 /// void setAspectProperties(const AspectProperties& state); 191 /// \endcode 192 /// 193 /// To embed both state and properties information, use EmbedStateAndProperties. 194 /// 195 /// It is possible to customize the way an EmbeddedPropertiesAspect interacts 196 /// with your Composite by using the 197 /// dart::common::detail::EmbeddedPropertiesAspect class directly instead of 198 /// inheriting this class. 199 DART_DECLARE_CLASS_WITH_VIRTUAL_BASE_BEGIN 200 template <class DerivedT, typename PropertiesDataT> 201 class EmbedProperties 202 : public virtual common::RequiresAspect< 203 common::EmbeddedPropertiesAspect<DerivedT, PropertiesDataT> > 204 { 205 public: 206 using Derived = DerivedT; 207 using Aspect = common::EmbeddedPropertiesAspect<Derived, PropertiesDataT>; 208 using AspectProperties = typename Aspect::Properties; 209 using AspectPropertiesData = typename Aspect::PropertiesData; 210 using Base = common::RequiresAspect<Aspect>; 211 212 // Forwarding constructor 213 template <typename... Args> EmbedProperties(Args &&...args)214 EmbedProperties(Args&&... args) : Base(std::forward<Args>(args)...) 215 { 216 // Do nothing 217 } 218 219 virtual ~EmbedProperties() = default; 220 getAspectProperties() const221 const AspectProperties& getAspectProperties() const 222 { 223 return mAspectProperties; 224 } 225 226 protected: 227 /// Aspect::Properties data, directly accessible to your derived class 228 AspectProperties mAspectProperties; 229 }; 230 DART_DECLARE_CLASS_WITH_VIRTUAL_BASE_END 231 232 //============================================================================== 233 /// This is an alternative to EmbedProperties which allows your class to also 234 /// inherit other Composite objects by listing them as the third (and later) 235 /// template arguments. 236 template <class DerivedT, typename PropertiesDataT, typename... CompositeBases> 237 class EmbedPropertiesOnTopOf : public CompositeJoiner< 238 EmbedProperties<DerivedT, PropertiesDataT>, 239 CompositeBases...> 240 { 241 public: 242 using Impl = EmbedProperties<DerivedT, PropertiesDataT>; 243 using Derived = typename Impl::Derived; 244 using AspectPropertiesData = typename Impl::AspectPropertiesData; 245 using AspectProperties = typename Impl::AspectProperties; 246 using Aspect = typename Impl::Aspect; 247 using Base = CompositeJoiner<Impl, CompositeBases...>; 248 using Impl::getAspectProperties; 249 250 // Forwarding constructor 251 template <typename... Args> EmbedPropertiesOnTopOf(Args &&...args)252 EmbedPropertiesOnTopOf(Args&&... args) 253 : Base(NoArg, std::forward<Args>(args)...) 254 { 255 // Do nothing 256 } 257 258 virtual ~EmbedPropertiesOnTopOf() = default; 259 260 protected: 261 using Impl::mAspectProperties; 262 }; 263 264 //============================================================================== 265 /// This is the implementation of a standard combination of embedded-state and 266 /// embedded-properties Aspect. Inherit the EmbedStateAndProperties (next class 267 /// down in the header) to use this Aspect implementation. 268 // 269 // Dev Note: We achieve "multiple inheritance" without the diamond of death 270 // issue by specifying detail::EmbeddedStateAspect as the base class of 271 // detail::EmbeddedPropertiesAspect. This allows their implementations to stack 272 // on top of each other without the conflict that would arise from both of them 273 // inheriting from common::Aspect. 274 template <class CompositeT, typename StateDataT, typename PropertiesDataT> 275 class EmbeddedStateAndPropertiesAspect 276 : public detail::EmbeddedPropertiesAspect< 277 detail::EmbeddedStateAspect< 278 CompositeTrackingAspect<CompositeT>, 279 EmbeddedStateAndPropertiesAspect< 280 CompositeT, 281 StateDataT, 282 PropertiesDataT>, 283 StateDataT>, 284 EmbeddedStateAndPropertiesAspect< 285 CompositeT, 286 StateDataT, 287 PropertiesDataT>, 288 PropertiesDataT> 289 { 290 public: 291 using Derived = EmbeddedStateAndPropertiesAspect< 292 CompositeT, 293 StateDataT, 294 PropertiesDataT>; 295 296 using AspectStateImpl = detail::EmbeddedStateAspect< 297 CompositeTrackingAspect<CompositeT>, 298 Derived, 299 StateDataT>; 300 301 using AspectPropertiesImpl = detail:: 302 EmbeddedPropertiesAspect<AspectStateImpl, Derived, PropertiesDataT>; 303 304 using AspectImpl = Derived; 305 306 using State = typename AspectStateImpl::State; 307 using StateData = typename AspectStateImpl::StateData; 308 309 using Properties = typename AspectPropertiesImpl::Properties; 310 using PropertiesData = typename AspectPropertiesImpl::PropertiesData; 311 312 using CompositeType = CompositeT; 313 314 EmbeddedStateAndPropertiesAspect(const EmbeddedStateAndPropertiesAspect&) 315 = delete; 316 317 virtual ~EmbeddedStateAndPropertiesAspect() = default; 318 319 /// Construct using nothing. The object will remain unaffected. EmbeddedStateAndPropertiesAspect()320 EmbeddedStateAndPropertiesAspect() : AspectPropertiesImpl() 321 { 322 // Do nothing 323 } 324 325 /// Construct using a State. The object's Properties will remain unaffected. EmbeddedStateAndPropertiesAspect(const StateData & state)326 EmbeddedStateAndPropertiesAspect(const StateData& state) 327 : AspectPropertiesImpl(state) 328 { 329 // Do nothing 330 } 331 332 /// Construct using Properties. The object's State will remain unaffected. EmbeddedStateAndPropertiesAspect(const PropertiesData & properties)333 EmbeddedStateAndPropertiesAspect(const PropertiesData& properties) 334 : AspectPropertiesImpl(properties) 335 { 336 // Do nothing 337 } 338 339 /// Construct using a State and Properties instance EmbeddedStateAndPropertiesAspect(const StateData & state,const PropertiesData & properties)340 EmbeddedStateAndPropertiesAspect( 341 const StateData& state, const PropertiesData& properties) 342 : AspectPropertiesImpl(properties, state) 343 { 344 // Do nothing 345 } 346 347 /// Construct using a Properties and State instance EmbeddedStateAndPropertiesAspect(const PropertiesData & properties,const StateData & state)348 EmbeddedStateAndPropertiesAspect( 349 const PropertiesData& properties, const StateData& state) 350 : AspectPropertiesImpl(properties, state) 351 { 352 // Do nothing 353 } 354 355 // Documentation inherited cloneAspect() const356 std::unique_ptr<Aspect> cloneAspect() const override 357 { 358 return std::make_unique<Derived>(this->getState(), this->getProperties()); 359 } 360 }; 361 362 //============================================================================== 363 /// Inherit this class to embed both State and Properties into your Composite 364 /// object. DerivedT is the name of your class, StateDataT is a "plain-old data" 365 /// structure that holds your state information, and PropertiesDataT is a 366 /// "plain-old data" structure that holds your properties information. 367 /// 368 /// Your derived class must implement the following functions: 369 /// 370 /// \code{.cpp} 371 /// void setAspectState(const AspectState& state); 372 /// void setAspectProperties(const AspectProperties& state); 373 /// \endcode 374 DART_DECLARE_CLASS_WITH_VIRTUAL_BASE_BEGIN 375 template <class DerivedT, typename StateDataT, typename PropertiesDataT> 376 class EmbedStateAndProperties : public virtual common::RequiresAspect< 377 common::EmbeddedStateAndPropertiesAspect< 378 DerivedT, 379 StateDataT, 380 PropertiesDataT> > 381 { 382 public: 383 using Derived = DerivedT; 384 using Aspect = common:: 385 EmbeddedStateAndPropertiesAspect<DerivedT, StateDataT, PropertiesDataT>; 386 387 using AspectState = typename Aspect::State; 388 using AspectStateData = typename Aspect::StateData; 389 390 using AspectProperties = typename Aspect::Properties; 391 using AspectPropertiesData = typename Aspect::PropertiesData; 392 using Base = common::RequiresAspect<Aspect>; 393 394 // Forwarding constructor 395 template <typename... Args> EmbedStateAndProperties(Args &&...args)396 EmbedStateAndProperties(Args&&... args) : Base(std::forward<Args>(args)...) 397 { 398 // Do nothing 399 } 400 401 virtual ~EmbedStateAndProperties() = default; 402 getAspectState() const403 const AspectState& getAspectState() const 404 { 405 return mAspectState; 406 } 407 getAspectProperties() const408 const AspectProperties& getAspectProperties() const 409 { 410 return mAspectProperties; 411 } 412 413 protected: 414 /// Aspect::State data, directly accessible to your derived class 415 AspectState mAspectState; 416 417 /// Aspect::Properties data, directly accessible to your derived class 418 AspectProperties mAspectProperties; 419 }; 420 DART_DECLARE_CLASS_WITH_VIRTUAL_BASE_END 421 422 //============================================================================== 423 /// This is an alternative to EmbedStateAndProperties which allows your class to 424 /// also inherit other Composite objects by listing them as the fourth (and 425 /// later) template arguments. 426 template < 427 class DerivedT, 428 typename StateDataT, 429 typename PropertiesDataT, 430 typename... CompositeBases> 431 class EmbedStateAndPropertiesOnTopOf 432 : public CompositeJoiner< 433 EmbedStateAndProperties<DerivedT, StateDataT, PropertiesDataT>, 434 CompositeBases...> 435 { 436 public: 437 using Impl = EmbedStateAndProperties<DerivedT, StateDataT, PropertiesDataT>; 438 using Derived = typename Impl::Derived; 439 using AspectStateData = typename Impl::AspectStateData; 440 using AspectState = typename Impl::AspectState; 441 using AspectPropertiesData = typename Impl::AspectPropertiesData; 442 using AspectProperties = typename Impl::AspectProperties; 443 using Aspect = typename Impl::Aspect; 444 using Impl::getAspectProperties; 445 using Impl::getAspectState; 446 using Base = CompositeJoiner<Impl, CompositeBases...>; 447 448 // Forwarding constructor 449 template <typename... Args> EmbedStateAndPropertiesOnTopOf(Args &&...args)450 EmbedStateAndPropertiesOnTopOf(Args&&... args) 451 : Base(NoArg, std::forward<Args>(args)...) 452 { 453 // Do nothing 454 } 455 456 virtual ~EmbedStateAndPropertiesOnTopOf() = default; 457 458 protected: 459 using Impl::mAspectProperties; 460 using Impl::mAspectState; 461 }; 462 463 } // namespace common 464 } // namespace dart 465 466 #endif // DART_COMMON_EMBEDDEDASPECT_HPP_ 467