QAnyStringView: construct from any T implicitly convertible to QString/QByteArray

This includes QDBusReply, QProperty, and QStringBuilder expressions.

The new constructor subsumes the QStringBuilder case without requiring
jumping though hoops to delay the definition of the ctor the way we
had to for the explicit QStringBuilder constructor, so remove the
explicit QStringBuilder one again.

[ChangeLog][QtCore][QAnyStringView] Can now be constructed from
anything that implicitly converts to either QString or QByteArray.

Fixes: QTBUG-105389
Change-Id: I0e584dd3e20d591381609a3329ef47cec7356ecc
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
This commit is contained in:
Marc Mutz 2022-08-07 22:18:38 +02:00 committed by Oliver Wolff
parent 24e8a693cd
commit 812a0d3125
4 changed files with 45 additions and 17 deletions

View File

@ -1279,7 +1279,7 @@ void QObject::setObjectName(QAnyStringView name)
d->extraData->objectName.removeBindingUnlessInWrapper();
if (d->extraData->objectName.value() != name) {
if (d->extraData->objectName != name) {
d->extraData->objectName.setValueBypassingBindings(name.toString());
d->extraData->objectName.notify(); // also emits a signal
}

View File

@ -1,3 +1,4 @@
// Copyright (C) 2022 The Qt Company Ltd.
// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QANYSTRINGVIEW_H
@ -9,14 +10,22 @@
#ifdef __cpp_impl_three_way_comparison
#include <compare>
#endif
#include <QtCore/q20functional.h>
#include <limits>
class tst_QAnyStringView;
QT_BEGIN_NAMESPACE
template <typename, typename> class QStringBuilder;
template <typename> struct QConcatenable;
namespace QtPrivate {
template <typename Tag, typename Result>
struct wrapped { using type = Result; };
template <typename Tag, typename Result>
using wrapped_t = typename wrapped<Tag, Result>::type;
} // namespace QtPrivate
class QAnyStringView
{
@ -43,6 +52,19 @@ private:
QtPrivate::IsContainerCompatibleWithQUtf8StringView<T>
>, bool>;
template <typename QStringOrQByteArray, typename T>
using if_convertible_to = std::enable_if_t<std::conjunction_v<
// need to exclude a bunch of stuff, because we take by universal reference:
std::negation<std::disjunction<
std::is_same<q20::remove_cvref_t<T>, QAnyStringView>, // don't make a copy/move ctor
std::is_pointer<std::decay_t<T>>, // const char*, etc
std::is_same<q20::remove_cvref_t<T>, QByteArray>,
std::is_same<q20::remove_cvref_t<T>, QString>
>>,
// this is what we're really after:
std::is_convertible<T, QStringOrQByteArray>
>, bool>;
// confirm we don't make an accidental copy constructor:
static_assert(QtPrivate::IsContainerCompatibleWithQStringView<QAnyStringView>::value == false);
static_assert(QtPrivate::IsContainerCompatibleWithQUtf8StringView<QAnyStringView>::value == false);
@ -155,15 +177,20 @@ public:
inline QAnyStringView(const QString &str) noexcept;
inline constexpr QAnyStringView(QLatin1StringView str) noexcept;
// defined in qstringbuilder.h
template <typename A, typename B>
inline QAnyStringView(const QStringBuilder<A, B> &expr,
typename QConcatenable<QStringBuilder<A, B>>::ConvertTo &&capacity = {});
template <typename Container, if_compatible_container<Container> = true>
constexpr QAnyStringView(const Container &c) noexcept
: QAnyStringView(std::data(c), lengthHelperContainer(c)) {}
template <typename Container, if_convertible_to<QString, Container> = true>
constexpr QAnyStringView(Container &&c, QtPrivate::wrapped_t<Container, QString> &&capacity = {})
//noexcept(std::is_nothrow_constructible_v<QString, Container>)
: QAnyStringView(capacity = std::forward<Container>(c)) {}
template <typename Container, if_convertible_to<QByteArray, Container> = true>
constexpr QAnyStringView(Container &&c, QtPrivate::wrapped_t<Container, QByteArray> &&capacity = {})
//noexcept(std::is_nothrow_constructible_v<QByteArray, Container>)
: QAnyStringView(capacity = std::forward<Container>(c)) {}
template <typename Char, if_compatible_char<Char> = true>
constexpr QAnyStringView(const Char &c) noexcept
: QAnyStringView{&c, 1} {}

View File

@ -452,15 +452,6 @@ QString &operator+=(QString &a, const QStringBuilder<A, B> &b)
return a;
}
//
// inline QAnyStringView members requiring QStringBuilder:
//
template <typename A, typename B>
QAnyStringView::QAnyStringView(const QStringBuilder<A, B> &expr,
typename QConcatenable<QStringBuilder<A, B>>::ConvertTo &&capacity)
: QAnyStringView(capacity = expr) {}
QT_END_NAMESPACE
#endif // QSTRINGBUILDER_H

View File

@ -59,6 +59,16 @@ static_assert(CanConvert<QLatin1String>);
static_assert(CanConvert<const char*>);
static_assert(CanConvert<QByteArray>);
template <typename T>
struct ImplicitlyConvertibleTo
{
operator T() const;
};
static_assert(CanConvert<ImplicitlyConvertibleTo<QString>>);
static_assert(CanConvert<ImplicitlyConvertibleTo<QByteArray>>);
static_assert(!CanConvert<ImplicitlyConvertibleTo<QLatin1StringView>>);
// QAnyStringView qchar_does_not_compile() { return QAnyStringView(QChar('a')); }
// QAnyStringView qlatin1string_does_not_compile() { return QAnyStringView(QLatin1String("a")); }
// QAnyStringView const_char_star_does_not_compile() { return QAnyStringView("a"); }