|
|
@@ -830,16 +830,27 @@ public:
|
|
|
void detach_from_objectdb();
|
|
|
_FORCE_INLINE_ ObjectID get_instance_id() const { return _instance_id; }
|
|
|
|
|
|
- template <typename T>
|
|
|
- static T *cast_to(Object *p_object) {
|
|
|
+ template <typename T, typename O>
|
|
|
+ static T *cast_to(O *p_object) {
|
|
|
// This is like dynamic_cast, but faster.
|
|
|
// The reason is that we can assume no virtual and multiple inheritance.
|
|
|
- return p_object && p_object->derives_from<T>() ? static_cast<T *>(p_object) : nullptr;
|
|
|
+ return p_object && p_object->template derives_from<T, O>() ? static_cast<T *>(p_object) : nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ template <typename T, typename O>
|
|
|
+ static const T *cast_to(const O *p_object) {
|
|
|
+ return p_object && p_object->template derives_from<T, O>() ? static_cast<const T *>(p_object) : nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ // cast_to versions for types that implicitly convert to Object.
|
|
|
+ template <typename T>
|
|
|
+ static T *cast_to(Object *p_object) {
|
|
|
+ return p_object && p_object->template derives_from<T, Object>() ? static_cast<T *>(p_object) : nullptr;
|
|
|
}
|
|
|
|
|
|
template <typename T>
|
|
|
static const T *cast_to(const Object *p_object) {
|
|
|
- return p_object && p_object->derives_from<T>() ? static_cast<const T *>(p_object) : nullptr;
|
|
|
+ return p_object && p_object->template derives_from<T, Object>() ? static_cast<const T *>(p_object) : nullptr;
|
|
|
}
|
|
|
|
|
|
enum {
|
|
|
@@ -872,7 +883,7 @@ public:
|
|
|
bool is_class(const String &p_class) const;
|
|
|
virtual bool is_class_ptr(void *p_ptr) const { return get_class_ptr_static() == p_ptr; }
|
|
|
|
|
|
- template <typename T>
|
|
|
+ template <typename T, typename O>
|
|
|
bool derives_from() const;
|
|
|
|
|
|
const StringName &get_class_name() const;
|
|
|
@@ -1041,27 +1052,23 @@ public:
|
|
|
bool predelete_handler(Object *p_object);
|
|
|
void postinitialize_handler(Object *p_object);
|
|
|
|
|
|
-template <typename T>
|
|
|
+template <typename T, typename O>
|
|
|
bool Object::derives_from() const {
|
|
|
- static_assert(std::is_base_of_v<Object, T>, "T must be derived from Object.");
|
|
|
- static_assert(std::is_same_v<std::decay_t<T>, typename T::self_type>, "T must use GDCLASS or GDSOFTCLASS.");
|
|
|
-
|
|
|
- // If there is an explicitly set ancestral class on the type, we can use that.
|
|
|
- if constexpr (T::static_ancestral_class != T::super_type::static_ancestral_class) {
|
|
|
- return _has_ancestry(T::static_ancestral_class);
|
|
|
+ if constexpr (std::is_base_of_v<T, O>) {
|
|
|
+ // We derive statically from T (or are the same class), so casting to it is trivial.
|
|
|
+ return true;
|
|
|
} else {
|
|
|
- return is_class_ptr(T::get_class_ptr_static());
|
|
|
- }
|
|
|
-}
|
|
|
+ static_assert(std::is_base_of_v<Object, O>, "derives_from can only be used with Object subclasses.");
|
|
|
+ static_assert(std::is_base_of_v<O, T>, "Cannot cast argument to T because T does not derive from the argument's known class.");
|
|
|
+ static_assert(std::is_same_v<std::decay_t<T>, typename T::self_type>, "T must use GDCLASS or GDSOFTCLASS.");
|
|
|
|
|
|
-template <>
|
|
|
-inline bool Object::derives_from<Object>() const {
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-template <>
|
|
|
-inline bool Object::derives_from<const Object>() const {
|
|
|
- return true;
|
|
|
+ // If there is an explicitly set ancestral class on the type, we can use that.
|
|
|
+ if constexpr (T::static_ancestral_class != T::super_type::static_ancestral_class) {
|
|
|
+ return _has_ancestry(T::static_ancestral_class);
|
|
|
+ } else {
|
|
|
+ return is_class_ptr(T::get_class_ptr_static());
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
class ObjectDB {
|