diff --git a/src/ifcparse/IfcBaseClass.h b/src/ifcparse/IfcBaseClass.h index 3c0202aeee..b296f3968a 100644 --- a/src/ifcparse/IfcBaseClass.h +++ b/src/ifcparse/IfcBaseClass.h @@ -41,26 +41,44 @@ namespace IfcUtil { return !not_this; } + template + std::enable_if_t::value && !std::is_same::value && !std::is_same::value> raise_error_on_concrete_class() const { + throw IfcParse::IfcException("Instance of type " + this->declaration().name() + " cannot be cast to " + T::Class().name()); + } + + template + std::enable_if_t::value || std::is_same::value || std::is_same::value> raise_error_on_concrete_class() const { + throw IfcParse::IfcException("Instance of type " + this->declaration().name() + " cannot be cast to base class"); + } + public: virtual const IfcEntityInstanceData& data() const = 0; virtual IfcEntityInstanceData& data() = 0; virtual const IfcParse::declaration& declaration() const = 0; template - T* as() { + T* as(bool do_throw = false) { // @todo: do not allow this to be null in the first place if (is_null(this)) { return static_cast(0); } - return dynamic_cast(this); + auto t = dynamic_cast(this); + if (do_throw && !t) { + raise_error_on_concrete_class(); + } + return t; } template - const T* as() const { + const T* as(bool do_throw = false) const { if (is_null(this)) { return static_cast(0); } - return dynamic_cast(this); + auto t = dynamic_cast(this); + if (do_throw && !t) { + raise_error_on_concrete_class(); + } + return t; } }; diff --git a/src/ifcparse/IfcSchema.h b/src/ifcparse/IfcSchema.h index d50ab8ba77..5b7c805429 100644 --- a/src/ifcparse/IfcSchema.h +++ b/src/ifcparse/IfcSchema.h @@ -34,6 +34,8 @@ class IfcEntityInstanceData; namespace IfcUtil { class IfcBaseClass; + class IfcBaseEntity; + class IfcBaseType; } namespace IfcParse {