JNI: clean up SFINAE constraints in QJniArray

Rename the predictate for checking whether a container type has the
required member functions and types to IfContiguousContainer (we
need size(), data(), and value_type members).
And since std::initializer_list always meets that criteria, remove the
constraint from the respective constructor.

Add an IfConvertible predicate to test whether the element type of
an existing array can be converted to the element type of the new
array.

Change-Id: I7e5ba31de9664088b027c277c068c948f2189238
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
(cherry picked from commit 468126d34a8c3a2fdd486768f935d13ebe565dd0)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Volker Hilsheimer 2024-06-05 14:46:31 +02:00 committed by Qt Cherry-pick Bot
parent a2b442fef8
commit 4ef415825c
2 changed files with 20 additions and 23 deletions

View File

@ -89,13 +89,13 @@ private:
class QT_TECH_PREVIEW_API QJniArrayBase
{
// for SFINAE'ing out the fromContainer named constructor
template <typename Container, typename = void> struct CanConvertHelper : std::false_type {};
template <typename Container>
struct CanConvertHelper<Container, std::void_t<decltype(std::data(std::declval<Container>())),
decltype(std::size(std::declval<Container>())),
typename Container::value_type
>
> : std::true_type {};
template <typename C, typename = void> struct IsContiguousContainerHelper : std::false_type {};
template <typename C>
struct IsContiguousContainerHelper<C, std::void_t<decltype(std::data(std::declval<C>())),
decltype(std::size(std::declval<C>())),
typename C::value_type
>
> : std::true_type {};
public:
using size_type = jsize;
@ -114,13 +114,12 @@ public:
return 0;
}
template <typename Container>
static constexpr bool canConvert = CanConvertHelper<q20::remove_cvref_t<Container>>::value;
template <typename Container>
using IfCanConvert = std::enable_if_t<canConvert<Container>, bool>;
template <typename Container
, IfCanConvert<Container> = true
>
template <typename C>
static constexpr bool isContiguousContainer = IsContiguousContainerHelper<q20::remove_cvref_t<C>>::value;
template <typename C>
using if_contiguous_container = std::enable_if_t<isContiguousContainer<C>, bool>;
template <typename Container, if_contiguous_container<Container> = true>
static auto fromContainer(Container &&container)
{
Q_ASSERT_X(size_t(std::size(container)) <= size_t((std::numeric_limits<size_type>::max)()),
@ -218,23 +217,21 @@ public:
QJniArray &operator=(const QJniArray &other) = default;
QJniArray &operator=(QJniArray &&other) noexcept = default;
template <typename Container
, IfCanConvert<Container> = true
>
template <typename Container, if_contiguous_container<Container> = true>
explicit QJniArray(Container &&container)
: QJniArrayBase(QJniArrayBase::fromContainer(std::forward<Container>(container)))
{
}
template <typename E = T
, IfCanConvert<std::initializer_list<E>> = true
>
Q_IMPLICIT inline QJniArray(std::initializer_list<T> list)
: QJniArrayBase(QJniArrayBase::fromContainer(list))
{
}
template <typename Other, std::enable_if_t<std::is_convertible_v<Other, Type>, bool> = true>
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))
{

View File

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