2626#include < string>
2727#include < utility>
2828#include < vector>
29+ #include < type_traits>
2930
3031#include " entityx/help/Pool.h"
3132#include " entityx/config.h"
@@ -40,7 +41,7 @@ typedef std::uint64_t uint64_t;
4041class EntityManager ;
4142
4243
43- template <typename C>
44+ template <typename C, typename EM = EntityManager >
4445class ComponentHandle ;
4546
4647/* * A convenience handle around an Entity::Id.
@@ -136,17 +137,17 @@ class Entity {
136137 template <typename C>
137138 void remove ();
138139
139- template <typename C>
140+ template <typename C, typename = typename std::enable_if<!std::is_const<C>::value>::type >
140141 ComponentHandle<C> component ();
141142
142- template <typename C>
143- const ComponentHandle<const C > component () const ;
143+ template <typename C, typename = typename std::enable_if<std::is_const<C>::value>::type >
144+ const ComponentHandle<C, const EntityManager > component () const ;
144145
145146 template <typename ... Components>
146147 std::tuple<ComponentHandle<Components>...> components ();
147148
148149 template <typename ... Components>
149- std::tuple<ComponentHandle<const Components>...> components () const ;
150+ std::tuple<ComponentHandle<const Components, const EntityManager >...> components () const ;
150151
151152 template <typename C>
152153 bool has_component () const ;
@@ -176,7 +177,7 @@ class Entity {
176177 * - If a component is removed from its host entity.
177178 * - If its host entity is destroyed.
178179 */
179- template <typename C>
180+ template <typename C, typename EM >
180181class ComponentHandle {
181182public:
182183 typedef C ComponentType;
@@ -208,12 +209,10 @@ class ComponentHandle {
208209private:
209210 friend class EntityManager ;
210211
211- ComponentHandle (EntityManager *manager, Entity::Id id) :
212+ ComponentHandle (EM *manager, Entity::Id id) :
212213 manager_ (manager), id_(id) {}
213- ComponentHandle (const EntityManager *manager, Entity::Id id) :
214- manager_ (const_cast <EntityManager*>(manager)), id_(id) {}
215214
216- EntityManager *manager_;
215+ EM *manager_;
217216 Entity::Id id_;
218217};
219218
@@ -268,7 +267,10 @@ template <typename Derived>
268267struct Component : public BaseComponent {
269268 public:
270269 typedef ComponentHandle<Derived> Handle;
270+ typedef ComponentHandle<const Derived, const EntityManager> ConstHandle;
271271
272+ private:
273+ friend class EntityManager ;
272274 // / Used internally for registration.
273275 static Family family ();
274276};
@@ -416,7 +418,7 @@ class EntityManager : entityx::help::NonCopyable {
416418 private:
417419 friend class EntityManager ;
418420
419- BaseView (EntityManager *manager) : manager_(manager) { mask_.set (); }
421+ explicit BaseView (EntityManager *manager) : manager_(manager) { mask_.set (); }
420422 BaseView (EntityManager *manager, ComponentMask mask) :
421423 manager_ (manager), mask_(mask) {}
422424
@@ -431,7 +433,7 @@ class EntityManager : entityx::help::NonCopyable {
431433 class UnpackingView {
432434 public:
433435 struct Unpacker {
434- Unpacker (ComponentHandle<Components> & ... handles) :
436+ explicit Unpacker (ComponentHandle<Components> & ... handles) :
435437 handles(std::tuple<ComponentHandle<Components> & ...>(handles...)) {}
436438
437439 void unpack (entityx::Entity &entity) const {
@@ -502,7 +504,7 @@ class EntityManager : entityx::help::NonCopyable {
502504 /* *
503505 * Return true if the given entity ID is still valid.
504506 */
505- bool valid (Entity::Id id) {
507+ bool valid (Entity::Id id) const {
506508 return id.index () < entity_version_.size () && entity_version_[id.index ()] == id.version ();
507509 }
508510
@@ -572,7 +574,7 @@ class EntityManager : entityx::help::NonCopyable {
572574 template <typename C, typename ... Args>
573575 ComponentHandle<C> assign (Entity::Id id, Args && ... args) {
574576 assert_valid (id);
575- const BaseComponent::Family family = Component <C>:: family ();
577+ const BaseComponent::Family family = component_family <C>();
576578 assert (!entity_component_mask_[id.index ()].test (family));
577579
578580 // Placement new into the component pool.
@@ -596,7 +598,7 @@ class EntityManager : entityx::help::NonCopyable {
596598 template <typename C>
597599 void remove (Entity::Id id) {
598600 assert_valid (id);
599- const BaseComponent::Family family = Component <C>:: family ();
601+ const BaseComponent::Family family = component_family <C>();
600602 const uint32_t index = id.index ();
601603
602604 // Find the pool for this component family.
@@ -617,7 +619,7 @@ class EntityManager : entityx::help::NonCopyable {
617619 template <typename C>
618620 bool has_component (Entity::Id id) const {
619621 assert_valid (id);
620- size_t family = Component <C>:: family ();
622+ size_t family = component_family <C>();
621623 // We don't bother checking the component mask, as we return a nullptr anyway.
622624 if (family >= component_pools_.size ())
623625 return false ;
@@ -632,10 +634,10 @@ class EntityManager : entityx::help::NonCopyable {
632634 *
633635 * @returns Pointer to an instance of C, or nullptr if the Entity::Id does not have that Component.
634636 */
635- template <typename C>
637+ template <typename C, typename = typename std::enable_if<!std::is_const<C>::value>::type >
636638 ComponentHandle<C> component (Entity::Id id) {
637639 assert_valid (id);
638- size_t family = Component <C>:: family ();
640+ size_t family = component_family <C>();
639641 // We don't bother checking the component mask, as we return a nullptr anyway.
640642 if (family >= component_pools_.size ())
641643 return ComponentHandle<C>();
@@ -650,17 +652,17 @@ class EntityManager : entityx::help::NonCopyable {
650652 *
651653 * @returns Component instance, or nullptr if the Entity::Id does not have that Component.
652654 */
653- template <typename C>
654- const ComponentHandle<const C > component (Entity::Id id) const {
655+ template <typename C, typename = typename std::enable_if<std::is_const<C>::value>::type >
656+ const ComponentHandle<C, const EntityManager > component (Entity::Id id) const {
655657 assert_valid (id);
656- size_t family = Component <C>:: family ();
658+ size_t family = component_family <C>();
657659 // We don't bother checking the component mask, as we return a nullptr anyway.
658660 if (family >= component_pools_.size ())
659- return ComponentHandle<const C >();
661+ return ComponentHandle<C, const EntityManager >();
660662 BasePool *pool = component_pools_[family];
661663 if (!pool || !entity_component_mask_[id.index ()][family])
662- return ComponentHandle<const C >();
663- return ComponentHandle<const C >(this , id);
664+ return ComponentHandle<C, const EntityManager >();
665+ return ComponentHandle<C, const EntityManager >(this , id);
664666 }
665667
666668 template <typename ... Components>
@@ -669,7 +671,7 @@ class EntityManager : entityx::help::NonCopyable {
669671 }
670672
671673 template <typename ... Components>
672- std::tuple<ComponentHandle<const Components>...> components (Entity::Id id) const {
674+ std::tuple<ComponentHandle<const Components, const EntityManager >...> components (Entity::Id id) const {
673675 return std::make_tuple (component<const Components>(id)...);
674676 }
675677
@@ -751,11 +753,18 @@ class EntityManager : entityx::help::NonCopyable {
751753 */
752754 void reset ();
753755
756+ // Retrieve the component family for a type.
757+ template <typename C>
758+ static BaseComponent::Family component_family () {
759+ return Component<typename std::remove_const<C>::type>::family ();
760+ }
761+
754762 private:
755763 friend class Entity ;
756- template <typename C>
764+ template <typename C, typename EM >
757765 friend class ComponentHandle ;
758766
767+
759768 inline void assert_valid (Entity::Id id) const {
760769 assert (id.index () < entity_component_mask_.size () && " Entity::Id ID outside entity vector range" );
761770 assert (entity_version_[id.index ()] == id.version () && " Attempt to access Entity via a stale Entity::Id" );
@@ -764,15 +773,15 @@ class EntityManager : entityx::help::NonCopyable {
764773 template <typename C>
765774 C *get_component_ptr (Entity::Id id) {
766775 assert (valid (id));
767- BasePool *pool = component_pools_[Component <C>:: family ()];
776+ BasePool *pool = component_pools_[component_family <C>()];
768777 assert (pool);
769778 return static_cast <C*>(pool->get (id.index ()));
770779 }
771780
772781 template <typename C>
773782 const C *get_component_ptr (Entity::Id id) const {
774783 assert_valid (id);
775- BasePool *pool = component_pools_[Component <C>:: family ()];
784+ BasePool *pool = component_pools_[component_family <C>()];
776785 assert (pool);
777786 return static_cast <const C*>(pool->get (id.index ()));
778787 }
@@ -785,7 +794,7 @@ class EntityManager : entityx::help::NonCopyable {
785794 template <typename C>
786795 ComponentMask component_mask () {
787796 ComponentMask mask;
788- mask.set (Component <C>:: family ());
797+ mask.set (component_family <C>());
789798 return mask;
790799 }
791800
@@ -815,7 +824,7 @@ class EntityManager : entityx::help::NonCopyable {
815824
816825 template <typename C>
817826 Pool<C> *accomodate_component () {
818- BaseComponent::Family family = Component <C>:: family ();
827+ BaseComponent::Family family = component_family <C>();
819828 if (component_pools_.size () <= family) {
820829 component_pools_.resize (family + 1 , nullptr );
821830 }
@@ -869,8 +878,7 @@ ComponentHandle<C> Entity::replace(Args && ... args) {
869878 auto handle = component<C>();
870879 if (handle) {
871880 *(handle.get ()) = C (std::forward<Args>(args) ...);
872- }
873- else {
881+ } else {
874882 handle = manager_->assign <C>(id_, std::forward<Args>(args) ...);
875883 }
876884 return handle;
@@ -882,16 +890,16 @@ void Entity::remove() {
882890 manager_->remove <C>(id_);
883891}
884892
885- template <typename C>
893+ template <typename C, typename >
886894ComponentHandle<C> Entity::component () {
887895 assert (valid ());
888896 return manager_->component <C>(id_);
889897}
890898
891- template <typename C>
892- const ComponentHandle<const C > Entity::component () const {
899+ template <typename C, typename >
900+ const ComponentHandle<C, const EntityManager > Entity::component () const {
893901 assert (valid ());
894- return manager_->component <const C>(id_);
902+ return const_cast < const EntityManager*>( manager_) ->component <const C>(id_);
895903}
896904
897905template <typename ... Components>
@@ -901,9 +909,9 @@ std::tuple<ComponentHandle<Components>...> Entity::components() {
901909}
902910
903911template <typename ... Components>
904- std::tuple<ComponentHandle<const Components>...> Entity::components () const {
912+ std::tuple<ComponentHandle<const Components, const EntityManager >...> Entity::components () const {
905913 assert (valid ());
906- return manager_->components <const Components...>(id_);
914+ return const_cast < const EntityManager*>( manager_) ->components <const Components...>(id_);
907915}
908916
909917
@@ -935,44 +943,44 @@ inline std::ostream &operator << (std::ostream &out, const Entity &entity) {
935943}
936944
937945
938- template <typename C>
939- inline ComponentHandle<C>::operator bool () const {
946+ template <typename C, typename EM >
947+ inline ComponentHandle<C, EM >::operator bool () const {
940948 return valid ();
941949}
942950
943- template <typename C>
944- inline bool ComponentHandle<C>::valid() const {
945- return manager_ && manager_->valid (id_) && manager_->has_component <C>(id_);
951+ template <typename C, typename EM >
952+ inline bool ComponentHandle<C, EM >::valid() const {
953+ return manager_ && manager_->valid (id_) && manager_->template has_component <C>(id_);
946954}
947955
948- template <typename C>
949- inline C *ComponentHandle<C>::operator -> () {
956+ template <typename C, typename EM >
957+ inline C *ComponentHandle<C, EM >::operator -> () {
950958 assert (valid ());
951- return manager_->get_component_ptr <C>(id_);
959+ return manager_->template get_component_ptr <C>(id_);
952960}
953961
954- template <typename C>
955- inline const C *ComponentHandle<C>::operator -> () const {
962+ template <typename C, typename EM >
963+ inline const C *ComponentHandle<C, EM >::operator -> () const {
956964 assert (valid ());
957- return manager_->get_component_ptr <C>(id_);
965+ return manager_->template get_component_ptr <C>(id_);
958966}
959967
960- template <typename C>
961- inline C *ComponentHandle<C>::get() {
968+ template <typename C, typename EM >
969+ inline C *ComponentHandle<C, EM >::get() {
962970 assert (valid ());
963- return manager_->get_component_ptr <C>(id_);
971+ return manager_->template get_component_ptr <C>(id_);
964972}
965973
966- template <typename C>
967- inline const C *ComponentHandle<C>::get() const {
974+ template <typename C, typename EM >
975+ inline const C *ComponentHandle<C, EM >::get() const {
968976 assert (valid ());
969- return manager_->get_component_ptr <C>(id_);
977+ return manager_->template get_component_ptr <C>(id_);
970978}
971979
972- template <typename C>
973- inline void ComponentHandle<C>::remove() {
980+ template <typename C, typename EM >
981+ inline void ComponentHandle<C, EM >::remove() {
974982 assert (valid ());
975- manager_->remove <C>(id_);
983+ manager_->template remove <C>(id_);
976984}
977985
978986
0 commit comments