Browse Source

Merge pull request #104825 from lawnjelly/faster_cast_to

[3.x] Use the in-built casting instead of `dynamic_cast` on all platforms
lawnjelly 4 months ago
parent
commit
106eeb8e60

+ 14 - 8
core/object.h

@@ -262,6 +262,16 @@ public:                                                             \
                                                                     \
 private:
 
+// This is a barebones version of GDCLASS,
+// only intended for simple classes deriving from Object
+// so that they can support the `Object::cast_to()` method.
+#define GDSOFTCLASS(m_class, m_inherits)                                                                                                \
+public:                                                                                                                                 \
+	typedef m_class self_type;                                                                                                          \
+	virtual bool is_class_ptr(void *p_ptr) const { return (p_ptr == get_class_ptr_static()) ? true : m_inherits::is_class_ptr(p_ptr); } \
+                                                                                                                                        \
+private:
+
 #define GDCLASS(m_class, m_inherits)                                                                                                    \
 private:                                                                                                                                \
 	void operator=(const m_class &p_rval) {}                                                                                            \
@@ -609,30 +619,26 @@ public:
 
 	template <class T>
 	static T *cast_to(Object *p_object) {
-#ifndef NO_SAFE_CAST
-		return dynamic_cast<T *>(p_object);
-#else
+		static_assert(std::is_base_of<Object, T>::value, "T must be derived from Object");
+		static_assert(std::is_same<std::decay_t<T>, typename T::self_type>::value, "T must use GDCLASS or GDSOFTCLASS");
 		if (!p_object)
 			return NULL;
 		if (p_object->is_class_ptr(T::get_class_ptr_static()))
 			return static_cast<T *>(p_object);
 		else
 			return NULL;
-#endif
 	}
 
 	template <class T>
 	static const T *cast_to(const Object *p_object) {
-#ifndef NO_SAFE_CAST
-		return dynamic_cast<const T *>(p_object);
-#else
+		static_assert(std::is_base_of<Object, T>::value, "T must be derived from Object");
+		static_assert(std::is_same<std::decay_t<T>, typename T::self_type>::value, "T must use GDCLASS or GDSOFTCLASS");
 		if (!p_object)
 			return NULL;
 		if (p_object->is_class_ptr(T::get_class_ptr_static()))
 			return static_cast<const T *>(p_object);
 		else
 			return NULL;
-#endif
 	}
 
 	enum {

+ 2 - 0
modules/camera/camera_osx.mm

@@ -200,6 +200,8 @@
 // CameraFeedOSX - Subclass for camera feeds in OSX
 
 class CameraFeedOSX : public CameraFeed {
+	GDSOFTCLASS(CameraFeedOSX, CameraFeed);
+
 private:
 	AVCaptureDevice *device;
 	MyCaptureSession *capture_session;

+ 4 - 0
modules/mbedtls/crypto_mbedtls.h

@@ -41,6 +41,8 @@
 class CryptoMbedTLS;
 class SSLContextMbedTLS;
 class CryptoKeyMbedTLS : public CryptoKey {
+	GDSOFTCLASS(CryptoKeyMbedTLS, CryptoKey);
+
 private:
 	mbedtls_pk_context pkey;
 	int locks = 0;
@@ -73,6 +75,8 @@ public:
 };
 
 class X509CertificateMbedTLS : public X509Certificate {
+	GDSOFTCLASS(X509CertificateMbedTLS, X509Certificate);
+
 private:
 	mbedtls_x509_crt cert;
 	int locks;

+ 1 - 0
modules/websocket/websocket_macros.h

@@ -63,6 +63,7 @@ protected:
 	CNAME *(*CNAME::_create)() = NULL;
 
 #define GDCIIMPL(IMPNAME, CNAME)                                      \
+	GDSOFTCLASS(IMPNAME, CNAME)                                       \
 public:                                                               \
 	static CNAME *_create() { return memnew(IMPNAME); }               \
 	static void make_default() { CNAME::_create = IMPNAME::_create; } \

+ 2 - 0
platform/osx/export/codesign.h

@@ -125,6 +125,8 @@ public:
 /*************************************************************************/
 
 class CodeSignBlob : public Reference {
+	GDSOFTCLASS(CodeSignBlob, Reference);
+
 public:
 	virtual PoolByteArray get_hash_sha1() const = 0;
 	virtual PoolByteArray get_hash_sha256() const = 0;