summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/tools/qstringview.cpp20
-rw-r--r--src/corelib/tools/qstringview.h4
-rw-r--r--tests/auto/corelib/tools/qstringview/tst_qstringview.cpp75
3 files changed, 99 insertions, 0 deletions
diff --git a/src/corelib/tools/qstringview.cpp b/src/corelib/tools/qstringview.cpp
index 0b1dac2f98..8d2fc996e9 100644
--- a/src/corelib/tools/qstringview.cpp
+++ b/src/corelib/tools/qstringview.cpp
@@ -240,6 +240,26 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn QStringView::QStringView(const Char *first, const Char *last)
+
+ Constructs a string view on \a first with length (\a last - \a first).
+
+ The range \c{[first,last)} must remain valid for the lifetime of
+ this string view object.
+
+ Passing \c nullptr as \a first is safe if \a last is nullptr, too,
+ and results in a null string view.
+
+ The behavior is undefined if \a last precedes \a first, or \a first
+ is \c nullptr and \a last is not.
+
+ This constructor only participates in overload resolution if \c Char
+ is a compatible character type. The compatible character types
+ are: \c QChar, \c ushort, \c char16_t and (on platforms, such as
+ Windows, where it is a 16-bit type) \c wchar_t.
+*/
+
+/*!
\fn QStringView::QStringView(const Char *str)
Constructs a string view on \a str. The length is determined
diff --git a/src/corelib/tools/qstringview.h b/src/corelib/tools/qstringview.h
index 62173f9765..fdbf644518 100644
--- a/src/corelib/tools/qstringview.h
+++ b/src/corelib/tools/qstringview.h
@@ -176,6 +176,10 @@ public:
: m_size((Q_ASSERT(len >= 0), Q_ASSERT(str || !len), len)),
m_data(castHelper(str)) {}
+ template <typename Char, if_compatible_char<Char> = true>
+ Q_DECL_CONSTEXPR QStringView(const Char *f, const Char *l)
+ : QStringView(f, l - f) {}
+
#ifdef Q_QDOC
template <typename Char, size_t N>
Q_DECL_CONSTEXPR QStringView(const Char (&array)[N]) Q_DECL_NOTHROW;
diff --git a/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp b/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
index 28f81e50e7..9617afb651 100644
--- a/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
+++ b/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
@@ -171,6 +171,38 @@ private Q_SLOTS:
#endif
}
+ void fromQCharRange() const
+ {
+ const QChar str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
+ fromRange(std::begin(str), std::end(str));
+ }
+
+ void fromUShortRange() const
+ {
+ const ushort str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
+ fromRange(std::begin(str), std::end(str));
+ }
+
+ void fromChar16TRange() const
+ {
+#if defined(Q_COMPILER_UNICODE_STRINGS)
+ const char16_t str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
+ fromRange(std::begin(str), std::end(str));
+#else
+ QSKIP("This test requires C++11 char16_t support enabled in the compiler");
+#endif
+ }
+
+ void fromWCharTRange() const
+ {
+#ifdef Q_OS_WIN
+ const wchar_t str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
+ fromRange(std::begin(str), std::end(str));
+#else
+ QSKIP("This is a Windows-only test");
+#endif
+ }
+
// std::basic_string
void fromStdStringWCharT() const
{
@@ -194,6 +226,8 @@ private:
void conversion_tests(String arg) const;
template <typename Char>
void fromLiteral(const Char *arg) const;
+ template <typename Char>
+ void fromRange(const Char *first, const Char *last) const;
template <typename Char, typename Container>
void fromContainer() const;
template <typename Char>
@@ -211,6 +245,10 @@ void tst_QStringView::constExpr() const
Q_STATIC_ASSERT(sv.empty());
Q_STATIC_ASSERT(sv.isEmpty());
Q_STATIC_ASSERT(sv.utf16() == nullptr);
+
+ constexpr QStringView sv2(sv.utf16(), sv.utf16() + sv.size());
+ Q_STATIC_ASSERT(sv2.isNull());
+ Q_STATIC_ASSERT(sv2.empty());
}
{
constexpr QStringView sv = QStringViewLiteral("");
@@ -219,6 +257,10 @@ void tst_QStringView::constExpr() const
Q_STATIC_ASSERT(sv.empty());
Q_STATIC_ASSERT(sv.isEmpty());
Q_STATIC_ASSERT(sv.utf16() != nullptr);
+
+ constexpr QStringView sv2(sv.utf16(), sv.utf16() + sv.size());
+ Q_STATIC_ASSERT(!sv2.isNull());
+ Q_STATIC_ASSERT(sv2.empty());
}
{
constexpr QStringView sv = QStringViewLiteral("Hello");
@@ -235,6 +277,11 @@ void tst_QStringView::constExpr() const
Q_STATIC_ASSERT(sv.at(4) == QLatin1Char('o'));
Q_STATIC_ASSERT(sv.back() == QLatin1Char('o'));
Q_STATIC_ASSERT(sv.last() == QLatin1Char('o'));
+
+ constexpr QStringView sv2(sv.utf16(), sv.utf16() + sv.size());
+ Q_STATIC_ASSERT(!sv2.isNull());
+ Q_STATIC_ASSERT(!sv2.empty());
+ Q_STATIC_ASSERT(sv2.size() == 5);
}
#if !defined(Q_OS_WIN) || defined(Q_COMPILER_UNICODE_STRINGS)
{
@@ -253,6 +300,11 @@ void tst_QStringView::constExpr() const
Q_STATIC_ASSERT(sv.at(4) == QLatin1Char('o'));
Q_STATIC_ASSERT(sv.back() == QLatin1Char('o'));
Q_STATIC_ASSERT(sv.last() == QLatin1Char('o'));
+
+ constexpr QStringView sv2(sv.utf16(), sv.utf16() + sv.size());
+ Q_STATIC_ASSERT(!sv2.isNull());
+ Q_STATIC_ASSERT(!sv2.empty());
+ Q_STATIC_ASSERT(sv2.size() == 5);
}
#else // storage_type is wchar_t
{
@@ -271,6 +323,11 @@ void tst_QStringView::constExpr() const
Q_STATIC_ASSERT(sv.at(4) == QLatin1Char('o'));
Q_STATIC_ASSERT(sv.back() == QLatin1Char('o'));
Q_STATIC_ASSERT(sv.last() == QLatin1Char('o'));
+
+ constexpr QStringView sv2(sv.utf16(), sv.utf16() + sv.size());
+ Q_STATIC_ASSERT(!sv2.isNull());
+ Q_STATIC_ASSERT(!sv2.empty());
+ Q_STATIC_ASSERT(sv2.size() == 5);
}
#endif
#endif
@@ -349,6 +406,24 @@ void tst_QStringView::fromLiteral(const Char *arg) const
conversion_tests(arg);
}
+template <typename Char>
+void tst_QStringView::fromRange(const Char *first, const Char *last) const
+{
+ const Char *null = nullptr;
+ QCOMPARE(QStringView(null, null).size(), 0);
+ QCOMPARE(QStringView(null, null).data(), nullptr);
+ QCOMPARE(QStringView(first, first).size(), 0);
+ QCOMPARE(static_cast<const void*>(QStringView(first, first).data()),
+ static_cast<const void*>(first));
+
+ const auto sv = QStringView(first, last);
+ QCOMPARE(sv.size(), last - first);
+ QCOMPARE(static_cast<const void*>(sv.data()),
+ static_cast<const void*>(first));
+
+ // can't call conversion_tests() here, as it requires a single object
+}
+
template <typename Char, typename Container>
void tst_QStringView::fromContainer() const
{