String-like containers: add implicit conversions towards std:: string views
In C++20 std::basic_string_view has gained a range constructor (like QStringView always had), but that range constructor has been made explicit. This means we can't just pass a QString(View) to a function taking a u16string_view. The consensus seems to be that that types that should implictly convert towards stdlib's string views should do that via implicit conversion operators. This patch adds them for * QByteArrayView => std::string_view * QString(View) => std::u16string_view * QUtf8StringView => std::string_view or std::u8string_view, depending on the storage_type QLatin1StringView doesn't have a matching std:: view so I'm not enabling its conversion. QByteArray poses a challenge, in that it already defines a conversion towards const char *. (One can disable that conversion with a macro.) That conversion makes it impossible to support: QByteArray ba; std::string_view sv1(ba); // 1 std::string_view sv2 = ba; // 2 because: * if only operator const char *() is defined, then (2) doesn't work (situation right now); * if both conversions to const char * and string_view are defined, then (1) is ambiguous on certain compilers (MSVC, QCC). Interestingly enough, not on GCC/Clang, but only in C++17 and later modes. I can't kill the conversion towards const char * (API break, and we use it *everywhere* in Qt), hence, QByteArray does not get the implicit conversion, at least not in this patch. [ChangeLog][QtCore][QByteArrayView] Added an implicit conversion operator towards std::string_view. [ChangeLog][QtCore][QString] Added an implicit conversion operator towards std::u16string_view. [ChangeLog][QtCore][QStringView] Added an implicit conversion operator towards std::u16string_view. [ChangeLog][QtCore][QUtf8StringView] Added an implicit conversion operator towards std::string_view (QUtf8StringView is using char as its storage type in Qt 6). Note that QUtf8StringView is planned to use char8_t in Qt 7, therefore it is expected that the conversion will change towards std::u8string_view in Qt 7. Change-Id: I6d3b64d211a386241ae157765cd1b03f531f909a Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
c07a3f10ef
commit
96d67da420
@ -301,6 +301,9 @@ public:
|
||||
[[nodiscard]] constexpr char front() const { Q_ASSERT(!empty()); return m_data[0]; }
|
||||
[[nodiscard]] constexpr char back() const { Q_ASSERT(!empty()); return m_data[m_size - 1]; }
|
||||
|
||||
[[nodiscard]] Q_IMPLICIT operator std::string_view() const noexcept
|
||||
{ return std::string_view(m_data, size_t(m_size)); }
|
||||
|
||||
//
|
||||
// Qt compatibility API:
|
||||
//
|
||||
|
@ -1032,3 +1032,12 @@
|
||||
|
||||
\sa QByteArray::isNull(), QByteArrayView
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QByteArrayView::operator std::string_view() const
|
||||
\since 6.7
|
||||
|
||||
Converts this QByteArrayView object to a \c{std::string_view} object.
|
||||
The returned view will have the same data pointer and length of
|
||||
this view.
|
||||
*/
|
||||
|
@ -2614,6 +2614,12 @@ QString::QString(QChar ch)
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*! \fn QString::operator std::u16string_view() const
|
||||
\since 6.7
|
||||
|
||||
Converts this QString object to a \c{std::u16string_view} object.
|
||||
*/
|
||||
|
||||
static bool needsReallocate(const QString &str, qsizetype newSize)
|
||||
{
|
||||
const auto capacityAtEnd = str.capacity() - str.data_ptr().freeSpaceAtBegin();
|
||||
|
@ -883,6 +883,8 @@ public:
|
||||
static inline QString fromStdU32String(const std::u32string &s);
|
||||
inline std::u32string toStdU32String() const;
|
||||
|
||||
Q_IMPLICIT inline operator std::u16string_view() const noexcept;
|
||||
|
||||
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
|
||||
static QString fromCFString(CFStringRef string);
|
||||
CFStringRef toCFString() const Q_DECL_CF_RETURNS_RETAINED;
|
||||
@ -1351,6 +1353,11 @@ inline std::u32string QString::toStdU32String() const
|
||||
return u32str;
|
||||
}
|
||||
|
||||
QString::operator std::u16string_view() const noexcept
|
||||
{
|
||||
return std::u16string_view(d.data(), size_t(d.size));
|
||||
}
|
||||
|
||||
#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
|
||||
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QString &);
|
||||
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QString &);
|
||||
|
@ -1411,4 +1411,13 @@ or the character \a ch
|
||||
\sa QStringTokenizer, qTokenize()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QStringView::operator std::u16string_view() const
|
||||
\since 6.7
|
||||
|
||||
Converts this QStringView object to a \c{std::u16string_view} object.
|
||||
The returned view will have the same data pointer and length of
|
||||
this view.
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -400,6 +400,9 @@ public:
|
||||
[[nodiscard]] constexpr QChar front() const { return Q_ASSERT(!empty()), QChar(m_data[0]); }
|
||||
[[nodiscard]] constexpr QChar back() const { return Q_ASSERT(!empty()), QChar(m_data[m_size - 1]); }
|
||||
|
||||
[[nodiscard]] Q_IMPLICIT operator std::u16string_view() const noexcept
|
||||
{ return std::u16string_view(m_data, size_t(m_size)); }
|
||||
|
||||
//
|
||||
// Qt compatibility API:
|
||||
//
|
||||
|
@ -274,6 +274,9 @@ public:
|
||||
[[nodiscard]] constexpr storage_type front() const { return Q_ASSERT(!empty()), m_data[0]; }
|
||||
[[nodiscard]] constexpr storage_type back() const { return Q_ASSERT(!empty()), m_data[m_size - 1]; }
|
||||
|
||||
[[nodiscard]] Q_IMPLICIT operator std::basic_string_view<storage_type>() const noexcept
|
||||
{ return std::basic_string_view<storage_type>(data(), size_t(size())); }
|
||||
|
||||
//
|
||||
// Qt compatibility API:
|
||||
//
|
||||
|
@ -695,3 +695,13 @@
|
||||
|
||||
\sa QByteArray::isNull(), QUtf8StringView
|
||||
*/
|
||||
|
||||
|
||||
/*! \fn QUtf8StringView::operator std::basic_string_view<storage_type>() const
|
||||
\since 6.7
|
||||
|
||||
Converts this QUtf8StringView object to a
|
||||
\c{std::basic_string_view} object. The returned view will have the
|
||||
same data pointer and length of this view. The character type of
|
||||
the returned view will be \c{storage_type}.
|
||||
*/
|
||||
|
@ -171,6 +171,7 @@ private slots:
|
||||
|
||||
void comparison() const;
|
||||
void compare() const;
|
||||
void std_stringview_conversion();
|
||||
|
||||
private:
|
||||
template <typename Data>
|
||||
@ -632,5 +633,30 @@ void tst_QByteArrayView::compare() const
|
||||
QVERIFY(alpha.compare(beta, Qt::CaseSensitive) > 0);
|
||||
}
|
||||
|
||||
void tst_QByteArrayView::std_stringview_conversion()
|
||||
{
|
||||
static_assert(std::is_convertible_v<QByteArrayView, std::string_view>);
|
||||
|
||||
QByteArrayView bav;
|
||||
std::string_view sv(bav);
|
||||
QCOMPARE(sv, std::string_view());
|
||||
|
||||
bav = "";
|
||||
sv = bav;
|
||||
QCOMPARE(bav.size(), 0);
|
||||
QCOMPARE(sv.size(), size_t(0));
|
||||
QCOMPARE(sv, std::string_view());
|
||||
|
||||
bav = "Hello";
|
||||
sv = bav;
|
||||
QCOMPARE(sv, std::string_view("Hello"));
|
||||
|
||||
bav = QByteArrayView::fromArray("Hello\0world");
|
||||
sv = bav;
|
||||
QCOMPARE(bav.size(), 12);
|
||||
QCOMPARE(sv.size(), size_t(12));
|
||||
QCOMPARE(sv, std::string_view("Hello\0world", 12));
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_QByteArrayView)
|
||||
#include "tst_qbytearrayview.moc"
|
||||
|
@ -696,6 +696,8 @@ private slots:
|
||||
void sliced();
|
||||
void chopped();
|
||||
void removeIf();
|
||||
|
||||
void std_stringview_conversion();
|
||||
};
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(tst_QString::DataOptions)
|
||||
|
||||
@ -8762,6 +8764,31 @@ void tst_QString::removeIf()
|
||||
QCOMPARE(a.removeIf(removeA), u"BcbC");
|
||||
}
|
||||
|
||||
void tst_QString::std_stringview_conversion()
|
||||
{
|
||||
static_assert(std::is_convertible_v<QString, std::u16string_view>);
|
||||
|
||||
QString s;
|
||||
std::u16string_view sv(s);
|
||||
QCOMPARE(sv, std::u16string_view());
|
||||
|
||||
s = u""_s;
|
||||
sv = s;
|
||||
QCOMPARE(s.size(), 0);
|
||||
QCOMPARE(sv.size(), size_t(0));
|
||||
QCOMPARE(sv, std::u16string_view());
|
||||
|
||||
s = u"Hello"_s;
|
||||
sv = s;
|
||||
QCOMPARE(sv, std::u16string_view(u"Hello"));
|
||||
|
||||
s = u"Hello\0world"_s;
|
||||
sv = s;
|
||||
QCOMPARE(s.size(), 11);
|
||||
QCOMPARE(sv.size(), size_t(11));
|
||||
QCOMPARE(sv, std::u16string_view(u"Hello\0world", 11));
|
||||
}
|
||||
|
||||
// QString's collation order is only supported during the lifetime as QCoreApplication
|
||||
QTEST_GUILESS_MAIN(tst_QString)
|
||||
|
||||
|
@ -258,6 +258,8 @@ private Q_SLOTS:
|
||||
void tokenize_data() const;
|
||||
void tokenize() const;
|
||||
|
||||
void std_stringview_conversion();
|
||||
|
||||
private:
|
||||
template <typename String>
|
||||
void conversion_tests(String arg) const;
|
||||
@ -879,5 +881,30 @@ void tst_QStringView::overloadResolution()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QStringView::std_stringview_conversion()
|
||||
{
|
||||
static_assert(std::is_convertible_v<QStringView, std::u16string_view>);
|
||||
|
||||
QStringView s;
|
||||
std::u16string_view sv(s);
|
||||
QCOMPARE(sv, std::u16string_view());
|
||||
|
||||
s = u"";
|
||||
sv = s;
|
||||
QCOMPARE(s.size(), 0);
|
||||
QCOMPARE(sv.size(), size_t(0));
|
||||
QCOMPARE(sv, std::u16string_view());
|
||||
|
||||
s = u"Hello";
|
||||
sv = s;
|
||||
QCOMPARE(sv, std::u16string_view(u"Hello"));
|
||||
|
||||
s = QStringView::fromArray(u"Hello\0world");
|
||||
sv = s;
|
||||
QCOMPARE(s.size(), 12);
|
||||
QCOMPARE(sv.size(), size_t(12));
|
||||
QCOMPARE(sv, std::u16string_view(u"Hello\0world\0", 12));
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_QStringView)
|
||||
#include "tst_qstringview.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user