Skip to content

Instantly share code, notes, and snippets.

@tylerreisinger
Created April 29, 2018 19:40
Show Gist options
  • Save tylerreisinger/63717311972a8eeb7dc0feb69e9c4fb3 to your computer and use it in GitHub Desktop.
Save tylerreisinger/63717311972a8eeb7dc0feb69e9c4fb3 to your computer and use it in GitHub Desktop.
diff --git a/entityx/Entity.h b/entityx/Entity.h
index 7c69e0a..7a205c7 100644
--- a/entityx/Entity.h
+++ b/entityx/Entity.h
@@ -34,6 +34,11 @@
#include "entityx/Event.h"
#include "entityx/help/NonCopyable.h"
+//Included on g++ and clang to demangle type_info::name().
+#if defined(__GNUG__) || defined(__clang__)
+#include <cxxabi.h>
+#endif
+
namespace entityx {
typedef std::uint32_t uint32_t;
@@ -170,6 +175,7 @@ public:
Entity::Id id_ = INVALID;
};
+std::ostream &operator << (std::ostream &out, const Entity::Id &id);
/**
* A ComponentHandle<C> is a wrapper around an instance of a component.
@@ -342,9 +348,11 @@ public:
virtual void remove_component(Entity e) = 0;
virtual void copy_component_to(Entity source, Entity target) = 0;
};
+template <typename C, typename = void>
+class ComponentHelper;
template <typename C>
-class ComponentHelper : public BaseComponentHelper {
+class ComponentHelper<C, std::enable_if_t<std::is_copy_constructible_v<C>>>: public BaseComponentHelper {
public:
void remove_component(Entity e) override {
e.remove<C>();
@@ -354,6 +362,33 @@ public:
}
};
+//If C has no copy constructor, we need to not call `assign_from_copy` or it is an error, even if
+//the component is never copied.
+//If copy_component_to is called on C, then we print a helpful error and abort.
+template <typename C>
+class ComponentHelper<C, std::enable_if_t<!std::is_copy_constructible_v<C>>>: public BaseComponentHelper {
+public:
+ void remove_component(Entity e) override {
+ e.remove<C>();
+ }
+ void copy_component_to(Entity source, Entity target) override {
+ int status = 0;
+//G++ and clang return mangled symbols in name. VC++ always returns the unmangled symbol directly.
+#if defined(__GNUG__) || defined(__clang__)
+ auto component_name = abi::__cxa_demangle(typeid(C).name(), 0, 0, &status);
+#else
+ auto component_name = typeid(C).name();
+#endif
+ std::cerr << "Error trying to copy a component of type '" << component_name
+ << "' from entity " << source.id() << " to entity " << target.id() << "."
+ << "'" << component_name << "' is not copy constructable.\n";
+ std::abort();
+#if defined(__GNUG__) || defined(__clang__)
+ free(component_name);
+#endif
+ }
+};
+
/**
* Manages Entity::Id creation and component assignment.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment