diff --git a/src/corelib/kernel/qjniobject.h b/src/corelib/kernel/qjniobject.h index 12cab4f360..75c896a728 100644 --- a/src/corelib/kernel/qjniobject.h +++ b/src/corelib/kernel/qjniobject.h @@ -63,13 +63,16 @@ public: jclass objectClass() const; QByteArray className() const; - template + template = true +#endif + > auto callMethod(const char *methodName, const char *signature, Args &&...args) const { if constexpr (QtJniTypes::isObjectType()) { return callObjectMethod(methodName, signature, std::forward(args)...); } else { - QtJniTypes::assertPrimitiveType(); QJniEnvironment env; jmethodID id = getCachedMethodID(env.jniEnv(), methodName, signature); if (id) { @@ -89,7 +92,11 @@ public: } } - template + template = true +#endif + > auto callMethod(const char *methodName, Args &&...args) const { constexpr auto signature = QtJniTypes::methodSignature(); @@ -100,7 +107,11 @@ public: } } - template + template = true +#endif + > QJniObject callObjectMethod(const char *methodName, Args &&...args) const { QtJniTypes::assertObjectType(); @@ -126,13 +137,16 @@ public: return callStaticMethod(clazz, id, std::forward(args)...); } - template + template = true +#endif + > static auto callStaticMethod(jclass clazz, jmethodID methodId, Args &&...args) { if constexpr (QtJniTypes::isObjectType()) { return callStaticObjectMethod(clazz, methodId, std::forward(args)...); } else { - QtJniTypes::assertPrimitiveType(); QJniEnvironment env; if (clazz && methodId) { if constexpr (std::is_same_v) { @@ -151,7 +165,11 @@ public: } } - template + template = true +#endif + > static auto callStaticMethod(const char *className, const char *methodName, Args &&...args) { QJniEnvironment env; @@ -159,7 +177,11 @@ public: return callStaticMethod(clazz, methodName, std::forward(args)...); } - template + template = true +#endif + > static auto callStaticMethod(jclass clazz, const char *methodName, Args &&...args) { constexpr auto signature = QtJniTypes::methodSignature(); @@ -175,7 +197,11 @@ public: static QJniObject callStaticObjectMethod(jclass clazz, jmethodID methodId, ...); - template + template = true +#endif + > static QJniObject callStaticObjectMethod(const char *className, const char *methodName, Args &&...args) { QtJniTypes::assertObjectType(); @@ -183,7 +209,11 @@ public: return callStaticObjectMethod(className, methodName, signature.data(), std::forward(args)...); } - template + template = true +#endif + > static QJniObject callStaticObjectMethod(jclass clazz, const char *methodName, Args &&...args) { QtJniTypes::assertObjectType(); @@ -191,12 +221,16 @@ public: return callStaticObjectMethod(clazz, methodName, signature.data(), std::forward(args)...); } - template auto getField(const char *fieldName) const + template = true +#endif + > + auto getField(const char *fieldName) const { if constexpr (QtJniTypes::isObjectType()) { return getObjectField(fieldName); } else { - QtJniTypes::assertPrimitiveType(); QJniEnvironment env; T res{}; constexpr auto signature = QtJniTypes::fieldSignature(); @@ -210,13 +244,16 @@ public: } } - template + template = true +#endif + > static auto getStaticField(const char *className, const char *fieldName) { if constexpr (QtJniTypes::isObjectType()) { return getStaticObjectField(className, fieldName); } else { - QtJniTypes::assertPrimitiveType(); QJniEnvironment env; jclass clazz = QJniObject::loadClass(className, env.jniEnv()); T res{}; @@ -238,13 +275,16 @@ public: } } - template + template = true +#endif + > static auto getStaticField(jclass clazz, const char *fieldName) { if constexpr (QtJniTypes::isObjectType()) { return getStaticObjectField(clazz, fieldName); } else { - QtJniTypes::assertPrimitiveType(); QJniEnvironment env; T res{}; constexpr auto signature = QtJniTypes::fieldSignature(); @@ -258,26 +298,36 @@ public: } } - template + template = true +#endif + > static auto getStaticField(const char *fieldName) { return getStaticField(QtJniTypes::className(), fieldName); } - template + template (), bool> = true +#endif + > QJniObject getObjectField(const char *fieldName) const { - QtJniTypes::assertObjectType(); constexpr auto signature = QtJniTypes::fieldSignature(); return getObjectField(fieldName, signature); } QJniObject getObjectField(const char *fieldName, const char *signature) const; - template + template (), bool> = true +#endif + > static QJniObject getStaticObjectField(const char *className, const char *fieldName) { - QtJniTypes::assertObjectType(); constexpr auto signature = QtJniTypes::fieldSignature(); return getStaticObjectField(className, fieldName, signature); } @@ -286,10 +336,13 @@ public: const char *fieldName, const char *signature); - template + template (), bool> = true +#endif + > static QJniObject getStaticObjectField(jclass clazz, const char *fieldName) { - QtJniTypes::assertObjectType(); constexpr auto signature = QtJniTypes::fieldSignature(); return getStaticObjectField(clazz, fieldName, signature); } @@ -297,9 +350,13 @@ public: static QJniObject getStaticObjectField(jclass clazz, const char *fieldName, const char *signature); - template void setField(const char *fieldName, T value) + template = true +#endif + > + void setField(const char *fieldName, T value) { - QtJniTypes::assertType(); QJniEnvironment env; constexpr auto signature = QtJniTypes::fieldSignature(); jfieldID id = getCachedFieldID(env.jniEnv(), fieldName, signature); @@ -309,10 +366,13 @@ public: } } - template + template = true +#endif + > void setField(const char *fieldName, const char *signature, T value) { - QtJniTypes::assertType(); QJniEnvironment env; jfieldID id = getCachedFieldID(env.jniEnv(), fieldName, signature); if (id) { @@ -321,10 +381,13 @@ public: } } - template + template = true +#endif + > static void setStaticField(const char *className, const char *fieldName, T value) { - QtJniTypes::assertType(); QJniEnvironment env; jclass clazz = QJniObject::loadClass(className, env.jniEnv()); if (!clazz) @@ -340,11 +403,14 @@ public: env.checkAndClearExceptions(); } - template + template = true +#endif + > static void setStaticField(const char *className, const char *fieldName, const char *signature, T value) { - QtJniTypes::assertType(); QJniEnvironment env; jclass clazz = QJniObject::loadClass(className, env.jniEnv()); @@ -359,11 +425,14 @@ public: } } - template + template = true +#endif + > static void setStaticField(jclass clazz, const char *fieldName, const char *signature, T value) { - QtJniTypes::assertType(); QJniEnvironment env; jfieldID id = getFieldID(env.jniEnv(), clazz, fieldName, signature, true); @@ -373,10 +442,13 @@ public: } } - template + template = true +#endif + > static void setStaticField(jclass clazz, const char *fieldName, T value) { - QtJniTypes::assertType(); QJniEnvironment env; constexpr auto signature = QtJniTypes::fieldSignature(); jfieldID id = getFieldID(env.jniEnv(), clazz, fieldName, signature, true); @@ -386,7 +458,11 @@ public: } } - template + template = true +#endif + > static void setStaticField(const char *fieldName, T value) { setStaticField(QtJniTypes::className(), fieldName, value); @@ -401,9 +477,9 @@ public: // This function takes ownership of the jobject and releases the local ref. before returning. static QJniObject fromLocalRef(jobject lref); - template QJniObject &operator=(T obj) + template + QJniObject &operator=(T obj) { - QtJniTypes::assertType(); assign(static_cast(obj)); return *this; } diff --git a/src/corelib/kernel/qjnitypes.h b/src/corelib/kernel/qjnitypes.h index 61dfe7bb89..067504c41d 100644 --- a/src/corelib/kernel/qjnitypes.h +++ b/src/corelib/kernel/qjnitypes.h @@ -5,6 +5,7 @@ #define QJNITYPES_H #include +#include #if defined(Q_QDOC) || defined(Q_OS_ANDROID) #include @@ -213,11 +214,12 @@ constexpr auto typeSignature() return String("D"); } else if constexpr (std::is_same_v) { return String("V"); - } else if constexpr (IsStringType::value) { - static_assert(!IsStringType::value, "Don't use a literal type, call data!"); - } else { - staticAssertTypeMismatch(); } + + // else: The return type becomes void, indicating that the typeSignature + // template is not implemented for the respective type. We use this to + // detect invalid types in the ValidSignatureTypes and ValidFieldType + // predicates below. } template @@ -260,12 +262,6 @@ static constexpr bool isArrayType() return signature.startsWith('['); } -template -static constexpr void assertPrimitiveType() -{ - static_assert(isPrimitiveType(), "Type needs to be a primitive JNI type!"); -} - template static constexpr void assertObjectType() { @@ -274,41 +270,51 @@ static constexpr void assertObjectType() "an object type signature registered)!"); } -template -static constexpr void assertType() -{ - static_assert(isPrimitiveType() || isObjectType(), - "Type needs to be a JNI type!"); -} +// A set of types is valid if typeSignature is implemented for all of them +template +constexpr bool ValidSignatureTypesDetail = !std::disjunction()), + void>..., + IsStringType...>::value; +template +using ValidSignatureTypes = std::enable_if_t< + ValidSignatureTypesDetail...>, bool>; -template +template +constexpr bool ValidFieldTypeDetail = isObjectType() || isPrimitiveType(); +template +using ValidFieldType = std::enable_if_t< + ValidFieldTypeDetail>, bool>; + + +template = true> static constexpr auto methodSignature() { return (String("(") + - ... + typeSignature>()) + ... + typeSignature>()) + String(")") + typeSignature(); } -template +template = true> static constexpr auto fieldSignature() { return QtJniTypes::typeSignature(); } -template +template = true> static constexpr auto constructorSignature() { return methodSignature(); } -template +template = true> static constexpr auto nativeMethodSignature(Ret (*)(JNIEnv *, jobject, Args...)) { return methodSignature(); } -template +template = true> static constexpr auto nativeMethodSignature(Ret (*)(JNIEnv *, jclass, Args...)) { return methodSignature();