JNI API review: minor cleanups of QJniArray

While the QJniArray type still is expected to be a QJniObject, we should
still make the QJniArrayBase type non-constructible by making the
constructors protected. Also make the destructor of that type protected
and add explicit default implementations of the SMF.

Name the SFINAE helper and predciate consistently as IfCanConvert.

Change-Id: I7a7c6a320fe9acb0758b53d94832d355c99cb6bb
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
(cherry picked from commit 4a19e97f70994bc8bb67e26533d18266b8a615bc)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Volker Hilsheimer 2023-12-18 12:28:56 +01:00 committed by Qt Cherry-pick Bot
parent 2d3ee8ac34
commit f7e42dc8b6
2 changed files with 33 additions and 21 deletions

View File

@ -70,18 +70,6 @@ class QJniArrayBase : public QJniObject
> : std::true_type {}; > : std::true_type {};
public: public:
explicit QJniArrayBase(jarray array)
: QJniObject(static_cast<jobject>(array))
{
static_assert(sizeof(QJniArrayBase) == sizeof(QJniObject),
"QJniArrayBase must have the same size as QJniObject!");
}
explicit QJniArrayBase(const QJniObject &object)
: QJniObject(object)
{}
explicit QJniArrayBase(QJniObject &&object) noexcept
: QJniObject(std::move(object))
{}
qsizetype size() const qsizetype size() const
{ {
@ -91,9 +79,11 @@ public:
} }
template <typename Container> template <typename Container>
static constexpr bool CanConvert = CanConvertHelper<Container>::value; static constexpr bool canConvert = CanConvertHelper<Container>::value;
template <typename Container>
using IfCanConvert = std::enable_if_t<canConvert<Container>, bool>;
template <typename Container template <typename Container
, std::enable_if_t<CanConvert<Container>, bool> = true , IfCanConvert<Container> = true
> >
static auto fromContainer(Container &&container) static auto fromContainer(Container &&container)
{ {
@ -136,6 +126,20 @@ public:
protected: protected:
QJniArrayBase() = default; QJniArrayBase() = default;
~QJniArrayBase() = default;
explicit QJniArrayBase(jarray array)
: QJniObject(static_cast<jobject>(array))
{
static_assert(sizeof(QJniArrayBase) == sizeof(QJniObject),
"QJniArrayBase must have the same size as QJniObject!");
}
explicit QJniArrayBase(const QJniObject &object)
: QJniObject(object)
{}
explicit QJniArrayBase(QJniObject &&object) noexcept
: QJniObject(std::move(object))
{}
template <typename ElementType, typename List, typename NewFn, typename SetFn> template <typename ElementType, typename List, typename NewFn, typename SetFn>
static auto makeArray(List &&list, NewFn &&newArray, SetFn &&setRegion); static auto makeArray(List &&list, NewFn &&newArray, SetFn &&setRegion);
@ -151,10 +155,19 @@ public:
using Type = T; using Type = T;
using const_iterator = const QJniArrayIterator<T>; using const_iterator = const QJniArrayIterator<T>;
using QJniArrayBase::QJniArrayBase; QJniArray() = default;
explicit QJniArray(jarray array) : QJniArrayBase(array) {}
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 Container template <typename Container
, std::enable_if_t<QJniArrayBase::CanConvert<Container>, bool> = true , IfCanConvert<Container> = true
> >
explicit QJniArray(Container &&container); explicit QJniArray(Container &&container);
@ -326,12 +339,11 @@ auto QJniArrayBase::makeObjectArray(List &&list)
template <typename T> template <typename T>
template <typename Container template <typename Container
, std::enable_if_t<QJniArrayBase::CanConvert<Container>, bool> , QJniArrayBase::IfCanConvert<Container>
> >
QJniArray<T>::QJniArray(Container &&container) QJniArray<T>::QJniArray(Container &&container)
: QJniArrayBase() : QJniArrayBase(QJniArrayBase::fromContainer(std::forward<Container>(container)))
{ {
*this = QJniArrayBase::fromContainer(std::forward<Container>(container));
} }
namespace QtJniTypes namespace QtJniTypes

View File

@ -815,7 +815,7 @@ auto QJniObject::LocalFrame<Args...>::convertToJni(T &&value)
return newLocalRef<jstring>(QJniObject::fromString(value)); return newLocalRef<jstring>(QJniObject::fromString(value));
} else if constexpr (QtJniTypes::IsJniArray<Type>::value) { } else if constexpr (QtJniTypes::IsJniArray<Type>::value) {
return value.arrayObject(); return value.arrayObject();
} else if constexpr (QJniArrayBase::CanConvert<T>) { } else if constexpr (QJniArrayBase::canConvert<T>) {
using QJniArrayType = decltype(QJniArrayBase::fromContainer(std::forward<T>(value))); using QJniArrayType = decltype(QJniArrayBase::fromContainer(std::forward<T>(value)));
using ArrayType = decltype(std::declval<QJniArrayType>().arrayObject()); using ArrayType = decltype(std::declval<QJniArrayType>().arrayObject());
return newLocalRef<ArrayType>(QJniArrayBase::fromContainer(std::forward<T>(value)).template object<jobject>()); return newLocalRef<ArrayType>(QJniArrayBase::fromContainer(std::forward<T>(value)).template object<jobject>());
@ -836,7 +836,7 @@ auto QJniObject::LocalFrame<Args...>::convertFromJni(QJniObject &&object)
return object.toString(); return object.toString();
} else if constexpr (QtJniTypes::IsJniArray<Type>::value) { } else if constexpr (QtJniTypes::IsJniArray<Type>::value) {
return T{object}; return T{object};
} else if constexpr (QJniArrayBase::CanConvert<Type>) { } else if constexpr (QJniArrayBase::canConvert<Type>) {
// if we were to create a QJniArray from Type... // if we were to create a QJniArray from Type...
using QJniArrayType = decltype(QJniArrayBase::fromContainer(std::declval<Type>())); using QJniArrayType = decltype(QJniArrayBase::fromContainer(std::declval<Type>()));
// then that QJniArray would have elements of type // then that QJniArray would have elements of type