summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qjniarray.h
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2024-07-10 17:25:43 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2024-07-19 22:16:51 +0200
commitebbf7b0fdf866190cd20e62d6b13c7c6808101da (patch)
treed0e3e3b310fe9bd189b7be4a349c23cf8f436d99 /src/corelib/kernel/qjniarray.h
parent82254fa836a21b5ec450a4ec7635e72403dded18 (diff)
JNI: clean up move semantics for QJniArray
Explicitly define (compiler-implemented) copy and move SMF's for QJniArrayBase; we need to, as the destructor is declared, so without them the compiler will implicitly convert an array to a QJniObject and call that constructor. Constrain the constructors and assignment operator from a QJniArray of another type so that no narrowing conversion is allowed. Due to the implicit conversion to QJniObject, we have to explicitly delete the overload for narrowing conversions. Use the detector we have in qobjectdefs_impl.h for that. Make the detection helpers private, and add test coverage. Pick-to: 6.8 Change-Id: I1b2bb4435d52223567d20bb55ceb0d516e3b0b15 Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src/corelib/kernel/qjniarray.h')
-rw-r--r--src/corelib/kernel/qjniarray.h65
1 files changed, 51 insertions, 14 deletions
diff --git a/src/corelib/kernel/qjniarray.h b/src/corelib/kernel/qjniarray.h
index 3f4968361dc..2cb5a98128a 100644
--- a/src/corelib/kernel/qjniarray.h
+++ b/src/corelib/kernel/qjniarray.h
@@ -159,6 +159,13 @@ class QJniArrayBase
>
> : std::true_type {};
+protected:
+ // these are used in QJniArray
+ template <typename From, typename To>
+ using if_convertible = std::enable_if_t<QtPrivate::AreArgumentsConvertibleWithoutNarrowingBase<From, To>::value, bool>;
+ template <typename From, typename To>
+ using unless_convertible = std::enable_if_t<!QtPrivate::AreArgumentsConvertibleWithoutNarrowingBase<From, To>::value, bool>;
+
public:
using size_type = jsize;
using difference_type = size_type;
@@ -196,7 +203,7 @@ public:
std::is_same<ElementType, QString>,
std::is_base_of<QtJniTypes::JObjectBase, ElementType>
>) {
- return QJniArray<ElementType>(makeObjectArray(std::forward<Container>(container)));
+ return QJniArray<ElementType>(makeObjectArray(std::forward<Container>(container)).arrayObject());
} else if constexpr (QtJniTypes::sameTypeForJni<ElementType, jfloat>) {
return makeArray<jfloat>(std::forward<Container>(container), &JNIEnv::NewFloatArray,
&JNIEnv::SetFloatArrayRegion);
@@ -233,6 +240,11 @@ protected:
QJniArrayBase() = default;
~QJniArrayBase() = default;
+ explicit QJniArrayBase(const QJniArrayBase &other) = default;
+ explicit QJniArrayBase(QJniArrayBase &&other) noexcept = default;
+ QJniArrayBase &operator=(const QJniArrayBase &other) = default;
+ QJniArrayBase &operator=(QJniArrayBase &&other) noexcept = default;
+
explicit QJniArrayBase(jarray array)
: m_object(static_cast<jobject>(array))
{
@@ -243,6 +255,16 @@ protected:
explicit QJniArrayBase(QJniObject &&object) noexcept
: m_object(std::move(object))
{}
+ QJniArrayBase &operator=(const QJniObject &object)
+ {
+ m_object = object;
+ return *this;
+ }
+ QJniArrayBase &operator=(QJniObject &&object) noexcept
+ {
+ m_object = std::move(object);
+ return *this;
+ }
JNIEnv *jniEnv() const noexcept { return QJniEnvironment::getJniEnv(); }
@@ -286,11 +308,34 @@ public:
explicit QJniArray(const QJniObject &object) : QJniArrayBase(object) {}
explicit QJniArray(QJniObject &&object) noexcept : QJniArrayBase(std::move(object)) {}
- // base class destructor is protected, so need to provide all SMFs
- QJniArray(const QJniArray &other) = default;
- QJniArray(QJniArray &&other) noexcept = default;
- QJniArray &operator=(const QJniArray &other) = default;
- QJniArray &operator=(QJniArray &&other) noexcept = default;
+ template <typename Other, if_convertible<Other, T> = true>
+ QJniArray(const QJniArray<Other> &other)
+ : QJniArrayBase(other)
+ {
+ }
+ template <typename Other, if_convertible<Other, T> = true>
+ QJniArray(QJniArray<Other> &&other) noexcept
+ : QJniArrayBase(std::move(other))
+ {
+ }
+ template <typename Other, if_convertible<Other, T> = true>
+ QJniArray &operator=(const QJniArray<Other> &other)
+ {
+ QJniArrayBase::operator=(QJniObject(other));
+ return *this;
+ }
+ template <typename Other, if_convertible<Other, T> = true>
+ QJniArray &operator=(QJniArray<Other> &&other) noexcept
+ {
+ QJniArray moved(std::move(other));
+ swap(moved);
+ return *this;
+ }
+ // explicitly delete to disable detour via operator QJniObject()
+ template <typename Other, unless_convertible<Other, T> = true>
+ QJniArray(const QJniArray<Other> &other) = delete;
+ template <typename Other, unless_convertible<Other, T> = true>
+ QJniArray(QJniArray<Other> &&other) noexcept = delete;
template <typename Container, if_contiguous_container<Container> = true>
explicit QJniArray(Container &&container)
@@ -303,14 +348,6 @@ public:
{
}
- template <typename Other>
- using if_convertible = std::enable_if_t<std::is_convertible_v<Other, T>, bool>;
-
- template <typename Other, if_convertible<Other> = true>
- QJniArray(QJniArray<Other> &&other)
- : QJniArrayBase(std::forward<QJniArray<Other>>(other))
- {
- }
~QJniArray() = default;
auto arrayObject() const