Ignition Physics

API Reference

1.2.0
detail/Entity.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2017 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 
18 #ifndef IGNITION_PHYSICS_DETAIL_ENTITY_HH_
19 #define IGNITION_PHYSICS_DETAIL_ENTITY_HH_
20 
21 #include <memory>
22 #include <tuple>
23 #include <utility>
24 
28 
29 namespace ignition
30 {
31  namespace physics
32  {
33  namespace detail
34  {
39  template <typename Policy, typename Features>
40  struct DeterminePlugin;
41 
43  template <typename Policy, typename... Features>
44  struct DeterminePlugin<Policy, std::tuple<Features...>>
45  {
46  using type = plugin::SpecializedPluginPtr<
47  typename Features::template Implementation<Policy>...>;
48  };
49 
54  template <typename T, typename Tuple>
55  struct TupleContainsBase;
56 
60  template <typename T, typename... Types>
61  struct TupleContainsBase<T, std::tuple<Types...>>
63  !std::is_same<
64  std::tuple<typename std::conditional<
65  std::is_base_of<T, Types>::value, Empty, Types>::type...>,
66  std::tuple<Types...>
67  >::value> { };
68 
70  template <typename ToFeatureTuple, typename FromFeatureList>
71  struct HasAllFeaturesImpl;
72 
73  template <typename FromFeatureList,
74  typename ToFeature1, typename... RemainingFeatures>
75  struct HasAllFeaturesImpl<
76  std::tuple<ToFeature1, RemainingFeatures...>, FromFeatureList>
77  {
78  static constexpr bool innerValue =
79  FromFeatureList::template HasFeature<ToFeature1>();
80 
81  static constexpr bool value = innerValue
82  && HasAllFeaturesImpl<std::tuple<RemainingFeatures...>,
83  FromFeatureList>::value;
84 
85  static_assert(
86  innerValue,
87  "YOU CANNOT IMPLICITLY UPCAST TO THIS ENTITY TYPE, BECAUSE IT "
88  "CONTAINS A FEATURE THAT IS NOT INCLUDED IN THE ENTITY THAT YOU "
89  "ARE CASTING FROM.");
90  };
91 
93  template <typename FromFeatureList>
94  struct HasAllFeaturesImpl<std::tuple<>, FromFeatureList>
95  {
96  static constexpr bool value = true;
97  };
98 
102  template <typename To, typename From>
103  struct HasAllFeatures
104  {
105  using ToFeatures = typename To::Features;
106  using FromFeatures = typename From::Features;
107 
108  static constexpr bool value =
109  HasAllFeaturesImpl<
110  typename ToFeatures::Features,
111  FromFeatures>::value;
112  };
113 
115  template <typename To, typename From, bool downcastable>
116  struct CheckForDowncastableMessage
117  {
118  static constexpr bool value =
119  TupleContainsBase<typename To::Identifier,
120  typename From::UpcastIdentifiers>::value;
121 
122  static_assert(
123  value, "YOU CANNOT UPCAST TO AN INCOMPATIBLE ENTITY TYPE.");
124  };
125 
126  // If an upcast from "To" to "From" is possible, then the user is trying
127  // to do an implicit downcast (base type to more derived type) which is
128  // not allowed. For that case, we will print a special message to help
129  // them out.
130  template <typename To, typename From>
131  struct CheckForDowncastableMessage<To, From, true>
132  {
133  static constexpr bool value =
134  TupleContainsBase<typename To::Identifier,
135  typename From::UpcastIdentifiers>::value;
136 
137  static_assert(
138  value,
139  "YOU CANNOT UPCAST TO AN ENTITY A MORE DERIVED TYPE. TO DOWNCAST "
140  "TO A MORE DERIVED TYPE (e.g. Joint to RevoluteJoint), USE THE "
141  "CASTING FEATURE OF THE BASE ENTITY, e.g. "
142  "Joint::CastToRevoluteJoint()");
143  };
144 
146  template <typename To, typename From>
147  struct UpcastCompatible
148  {
149  static_assert(
151  "YOU CAN ONLY CAST BETWEEN ENTITIES THAT HAVE THE SAME POLICY ("
152  "e.g. FeaturePolicy3d, FeaturePolicy2d, FeaturePolicy3f). THE "
153  "REQUESTED CONVERSION IS NOT ADMISSIBLE.");
154 
155  static_assert(HasAllFeatures<To, From>::value);
156 
157  static_assert(CheckForDowncastableMessage<To, From,
158  TupleContainsBase<
159  typename From::Identifier,
160  typename To::UpcastIdentifiers>::value>::value);
161 
162  static_assert(
164  "CANNOT CAST FROM A CONST-QUALIFIED ENTITY TO AN ENTITY WITHOUT A "
165  "CONST-QUALIFIER.");
166  };
167  }
168 
170  template <typename EntityT>
172  {
173  *this = _other;
174  }
175 
177  template <typename EntityT>
179  -> EntityPtr&
180  {
181  if (_other)
182  {
183  this->entity.emplace(_other.entity->pimpl, _other.entity->identity);
184  }
185  return *this;
186  }
187 
189  template <typename EntityT>
191  : entity(std::nullopt)
192  {
193  // Do nothing
194  }
195 
197  template <typename EntityT>
199  : entity(std::nullopt)
200  {
201  // Do nothing
202  }
203 
205  template <typename EntityT>
207  {
208  this->entity.reset();
209  return *this;
210  }
211 
213  template <typename EntityT>
214  auto EntityPtr<EntityT>::operator=(std::nullopt_t) -> EntityPtr&
215  {
216  this->entity.reset();
217  return *this;
218  }
219 
221  template <typename EntityT>
222  // cppcheck-suppress syntaxError
223  template <typename Pimpl>
225  const std::shared_ptr<Pimpl> &_pimpl,
226  const Identity &_identity)
227  {
228  // EntityPtr should never accept invalid identities, otherwise users will
229  // have to check for validity of their entities in two places instead of
230  // one.
231  if (_identity)
232  {
233  this->entity.emplace(_pimpl, _identity);
234  }
235  }
236 
238  template <typename EntityT>
239  template <typename OtherEntityT>
241  {
242  *this = _other;
243  }
244 
246  template <typename EntityT>
247  template <typename OtherEntityT>
249  -> EntityPtr&
250  {
251  // Verify that an upcast is okay for these types
252  detail::UpcastCompatible<EntityT, OtherEntityT>();
253 
254  // If _other doesn't contain an entity clear our entity and return
255  if (!_other.entity)
256  {
257  this->entity.reset();
258  return *this;
259  }
260 
261  // If _other.entity doesn't have a valid identity, we don't want to accept
262  // it. EntityPtr should never accept invalid identities, otherwise users
263  // will have to check for validity of their entities in two places instead
264  // of one.
265  if (!_other.entity->identity)
266  {
267  this->entity.reset();
268  return *this;
269  }
270 
271  if (this->entity)
272  {
273  // Emplace to set the identity because assigment is not possible. Use
274  // the entity's own pimpl temporarily for the construction and copy
275  // assign the pimpl afterward
276  this->entity.emplace(this->entity->pimpl, _other.entity->identity);
277  // Avoid reallocating the pimpl
278  *this->entity->pimpl = *_other.entity->pimpl;
279  }
280  else
281  {
283  std::make_shared<typename EntityT::Pimpl>(
284  *_other.entity->pimpl);
285 
286  this->entity.emplace(std::move(newPimpl), _other.entity->identity);
287  }
288 
289  return *this;
290  }
291 
293  template <typename EntityT>
295  {
296  return &(this->entity.value());
297  }
298 
300  template <typename EntityT>
302  {
303  return this->entity.value();
304  }
305 
307  template <typename EntityT>
309  {
310  return this->entity.has_value();
311  }
312 
314  template <typename EntityT>
316  {
317  return this->entity.has_value();
318  }
319 
321  template <typename EntityT>
323  {
324  if (!(*this))
326 
327  return std::hash<std::size_t>()(this->entity->EntityID());
328  }
329 
331  template <typename Policy, typename Features>
333  {
334  return this->identity;
335  }
336 
338  template <typename Policy, typename Features>
340  {
341  return this->identity.id;
342  }
343 
345  template <typename Policy, typename Features>
346  const std::shared_ptr<void> &
348  {
349  return this->identity.ref;
350  }
351 
353  template <typename Policy, typename Features>
355  const std::shared_ptr<Pimpl> &_pimpl,
356  const Identity &_identity)
357  : pimpl(_pimpl),
358  identity(_identity)
359  {
360  // Do nothing
361  }
362 
364  template <typename Policy, typename Features>
366  std::shared_ptr<Pimpl> &&_pimpl,
367  const Identity &_identity)
368  : pimpl(std::move(_pimpl)),
369  identity(_identity)
370  {
371  // Do nothing
372  }
373 
375  template <typename Policy, typename Features>
376  template <typename FeatureT>
377  typename FeatureT::template Implementation<Policy>*
379  {
380  return (*this->pimpl)->template QueryInterface<
381  typename FeatureT::template Implementation<Policy>>();
382  }
383 
385  template <typename Policy, typename Features>
386  template <typename FeatureT>
387  const typename FeatureT::template Implementation<Policy>*
389  {
390  return (*this->pimpl)->template QueryInterface<
391  typename FeatureT::template Implementation<Policy>>();
392  }
393 
395  #define DETAIL_IGN_PHYSICS_ENTITY_PTR_IMPLEMENT_OPERATOR(op) \
396  template <typename EntityT> \
397  template <typename OtherEntityT> \
398  bool EntityPtr<EntityT>::operator op (\
399  const EntityPtr<OtherEntityT> &_other) const \
400  { \
401  /* If either ptr is invalid, we always return false */ \
402  if (!(*this) || !_other) \
403  return false; \
404  return (this->entity->EntityID() op _other.entity->EntityID()); \
405  }
406 
413 
415  // Operators to compare with nullptr and nullopt
416  template <typename EntityT>
417  bool operator==(std::nullptr_t, const EntityPtr<EntityT> &_ptr)
418  {
419  return !_ptr.Valid();
420  }
421 
423  template <typename EntityT>
425  {
426  return !_ptr.Valid();
427  }
428 
430  // Operators to compare with nullptr and nullopt
431  template <typename EntityT>
433  {
434  return !(_ptr == nullptr);
435  }
436 
438  template <typename EntityT>
440  {
441  return !(_ptr == nullptr);
442  }
443 
445  template <typename EntityT>
446  bool operator==(std::nullopt_t, const EntityPtr<EntityT> &_ptr)
447  {
448  return !_ptr.Valid();
449  }
450 
452  template <typename EntityT>
453  bool operator==(const EntityPtr<EntityT> &_ptr, std::nullopt_t)
454  {
455  return !_ptr.Valid();
456  }
457 
459  template <typename EntityT>
460  bool operator!=(std::nullopt_t, const EntityPtr<EntityT> &_ptr)
461  {
462  return !(_ptr == nullptr);
463  }
464 
466  template <typename EntityT>
467  bool operator!=(const EntityPtr<EntityT> &_ptr, std::nullopt_t)
468  {
469  return !(_ptr == nullptr);
470  }
471  }
472 }
473 
474 // Note that opening up namespace std is legal here because we are specializing
475 // a templated structure from the STL, which is permitted (and even encouraged).
476 namespace std
477 {
481  template <typename EntityT>
482  struct hash<ignition::physics::EntityPtr<EntityT>>
483  {
485  {
486  return ptr.Hash();
487  }
488  };
489 }
490 
491 #endif
Definition: Entity.hh:41
bool operator!=(const EntityPtr< EntityT > &_ptr, std::nullopt_t)
Definition: detail/Entity.hh:467
This is the base class of all "proxy objects". The "proxy objects" are essentially interfaces into th...
Definition: Identity.hh:32
STL namespace.
This class contains fields that identify an Entity. We use this separate class in order to have tight...
Definition: Identity.hh:73
EntityPtr & operator=(EntityPtr &&)=default
bool Valid() const
Check whether this is pointing at a valid Entity.
Definition: detail/Entity.hh:308
std::size_t Hash() const
Produces a hash for the Entity that this EntityPtr is referring to. This function allows EntityPtr in...
Definition: detail/Entity.hh:322
TemplatePluginPtr< SpecializedPlugin< SpecInterfaces... > > SpecializedPluginPtr
T move(T... args)
const std::size_t INVALID_ENTITY_ID
This constant-value should be used to indicate that an Entity ID is invalid (i.e. does not refer to a...
Definition: Entity.hh:37
#define DETAIL_IGN_PHYSICS_ENTITY_PTR_IMPLEMENT_OPERATOR(op)
Definition: detail/Entity.hh:395
Contains a static constexpr field named value which will be true if the type From has a const-quality...
Definition: TemplateHelpers.hh:58
bool operator==(const EntityPtr< EntityT > &_ptr, std::nullopt_t)
Definition: detail/Entity.hh:453
size_t operator()(const EntityPtr< EntityT > &ptr) const
Definition: detail/Entity.hh:484