diff --git a/.gitignore b/.gitignore index 2ae4ed78..de469da2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ CMakeLists.txt.user build* *.swp .settings +# ignore mac temporal files +.DS_Store diff --git a/src/OpenMesh/Core/Utils/BaseProperty.hh b/src/OpenMesh/Core/Utils/BaseProperty.hh index 9991b3ba..1e63d6d3 100644 --- a/src/OpenMesh/Core/Utils/BaseProperty.hh +++ b/src/OpenMesh/Core/Utils/BaseProperty.hh @@ -80,13 +80,13 @@ public: /// /// \param _name Optional textual name for the property. /// - BaseProperty(const std::string& _name = "") - : name_(_name), persistent_(false) + BaseProperty(const std::string& _name = "", const std::string& _internal_type_name = "" ) + : name_(_name), internal_type_name_(_internal_type_name), persistent_(false) {} /// \brief Copy constructor BaseProperty(const BaseProperty & _rhs) - : name_( _rhs.name_ ), persistent_( _rhs.persistent_ ) {} + : name_( _rhs.name_ ), internal_type_name_(_rhs.internal_type_name_), persistent_( _rhs.persistent_ ) {} /// Destructor. virtual ~BaseProperty() {} @@ -119,6 +119,9 @@ public: // named property interface /// Return the name of the property const std::string& name() const { return name_; } + /// Return internal type name of the property for type safe casting alternative to runtime information + const std::string& internal_type_name() const { return internal_type_name_; } + virtual void stats(std::ostream& _ostr) const; public: // I/O support @@ -173,6 +176,7 @@ protected: private: std::string name_; + std::string internal_type_name_; bool persistent_; }; diff --git a/src/OpenMesh/Core/Utils/Property.hh b/src/OpenMesh/Core/Utils/Property.hh index 629225c6..7f913ec1 100644 --- a/src/OpenMesh/Core/Utils/Property.hh +++ b/src/OpenMesh/Core/Utils/Property.hh @@ -99,8 +99,10 @@ public: public: /// Default constructor - explicit PropertyT(const std::string& _name = "") - : BaseProperty(_name) + explicit PropertyT( + const std::string& _name = "", + const std::string& _internal_type_name = "") + : BaseProperty(_name, _internal_type_name) {} /// Copy constructor @@ -173,17 +175,17 @@ public: // data access interface return &data_[0]; } - - /// Get reference to property vector (be careful, improper usage, e.g. resizing, may crash OpenMesh!!!) - vector_type& data_vector() { - return data_; - } - - /// Const access to property vector - const vector_type& data_vector() const { - return data_; - } - + + /// Get reference to property vector (be careful, improper usage, e.g. resizing, may crash OpenMesh!!!) + vector_type& data_vector() { + return data_; + } + + /// Const access to property vector + const vector_type& data_vector() const { + return data_; + } + /// Access the i'th element. No range check is performed! reference operator[](int _idx) { @@ -230,8 +232,8 @@ public: public: - explicit PropertyT(const std::string& _name = "") - : BaseProperty(_name) + explicit PropertyT(const std::string& _name = "", const std::string& _internal_type_name="" ) + : BaseProperty(_name, _internal_type_name) { } public: // inherited from BaseProperty @@ -337,17 +339,17 @@ public: public: - - /// Get reference to property vector (be careful, improper usage, e.g. resizing, may crash OpenMesh!!!) - vector_type& data_vector() { - return data_; - } - - /// Const access to property vector - const vector_type& data_vector() const { - return data_; - } - + + /// Get reference to property vector (be careful, improper usage, e.g. resizing, may crash OpenMesh!!!) + vector_type& data_vector() { + return data_; + } + + /// Const access to property vector + const vector_type& data_vector() const { + return data_; + } + /// Access the i'th element. No range check is performed! reference operator[](int _idx) { @@ -394,8 +396,8 @@ public: public: - explicit PropertyT(const std::string& _name = "") - : BaseProperty(_name) + explicit PropertyT(const std::string& _name = "", const std::string& _internal_type_name="" ) + : BaseProperty(_name, _internal_type_name) { } public: // inherited from BaseProperty diff --git a/src/OpenMesh/Core/Utils/PropertyContainer.hh b/src/OpenMesh/Core/Utils/PropertyContainer.hh index dcc9a3ac..297d16b9 100644 --- a/src/OpenMesh/Core/Utils/PropertyContainer.hh +++ b/src/OpenMesh/Core/Utils/PropertyContainer.hh @@ -44,12 +44,8 @@ #ifndef OPENMESH_PROPERTYCONTAINER #define OPENMESH_PROPERTYCONTAINER -// Use static casts when not debugging -#ifdef NDEBUG -#define OM_FORCE_STATIC_CAST -#endif - #include +#include //----------------------------------------------------------------------------- namespace OpenMesh @@ -104,7 +100,7 @@ public: int idx=0; for ( ; p_it!=p_end && *p_it!=nullptr; ++p_it, ++idx ) {}; if (p_it==p_end) properties_.push_back(nullptr); - properties_[idx] = new PropertyT(_name); + properties_[idx] = new PropertyT(_name, get_type_name() ); // create a new property with requested name and given (system dependent) internal typename return BasePropHandleT(idx); } @@ -117,10 +113,7 @@ public: { if (*p_it != nullptr && (*p_it)->name() == _name //skip deleted properties -// Skip type check -#ifndef OM_FORCE_STATIC_CAST - && dynamic_cast*>(properties_[idx]) != nullptr //check type -#endif + && (*p_it)->internal_type_name() == get_type_name() // new check type ) { return BasePropHandleT(idx); @@ -146,13 +139,10 @@ public: { assert(_h.idx() >= 0 && _h.idx() < (int)properties_.size()); assert(properties_[_h.idx()] != nullptr); -#ifdef OM_FORCE_STATIC_CAST - return *static_cast *> (properties_[_h.idx()]); -#else - PropertyT* p = dynamic_cast*>(properties_[_h.idx()]); + assert( properties_[_h.idx()]->internal_type_name() == get_type_name() ); + PropertyT *p = static_cast< PropertyT* > (properties_[_h.idx()]); assert(p != nullptr); return *p; -#endif } @@ -160,13 +150,10 @@ public: { assert(_h.idx() >= 0 && _h.idx() < (int)properties_.size()); assert(properties_[_h.idx()] != nullptr); -#ifdef OM_FORCE_STATIC_CAST - return *static_cast*>(properties_[_h.idx()]); -#else - PropertyT* p = dynamic_cast*>(properties_[_h.idx()]); + assert( properties_[_h.idx()]->internal_type_name() == get_type_name() ); + PropertyT *p = static_cast< PropertyT* > (properties_[_h.idx()]); assert(p != nullptr); return *p; -#endif } diff --git a/src/OpenMesh/Core/Utils/typename.hh b/src/OpenMesh/Core/Utils/typename.hh new file mode 100644 index 00000000..f67ae18b --- /dev/null +++ b/src/OpenMesh/Core/Utils/typename.hh @@ -0,0 +1,26 @@ +#pragma once + +/// Get an internal name for a type +/// Important, this is depends on compilers and versions, do NOT use in file formats! +/// This provides property type safety when only limited RTTI is available +/// Solution adapted from OpenVolumeMesh + +#include +#include + +namespace OpenMesh { + +template +std::string get_type_name() +{ +#ifdef _MSC_VER + // MSVC'S type_name returns only a friendly name with name() method, + // to get a unique name use raw_name() method instead + return typeid(T).raw_name(); +#else + // GCC and clang curently return mangled name as name(), there is no raw_name() method + return typeid(T).name(); +#endif +} + +}