diff --git a/src/corelib/tools/qstringview.cpp b/src/corelib/tools/qstringview.cpp index ec77e11740..341746e80a 100644 --- a/src/corelib/tools/qstringview.cpp +++ b/src/corelib/tools/qstringview.cpp @@ -260,9 +260,33 @@ QT_BEGIN_NAMESPACE Passing \c nullptr as \a str is safe and results in a null string view. - 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. + This constructor only participates in overload resolution if \a + str is not an array and 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 (&string)[N]) + + Constructs a string view on the character string literal \a string. + The length is set to \c{N-1}, excluding the trailing \{Char(0)}. + If you need the full array, use the constructor from pointer and + size instead: + + \code + auto sv = QStringView(array, std::size(array)); // using C++17 std::size() + \endcode + + \a string must remain valid for the lifetime of this string view + object. + + This constructor only participates in overload resolution if \a + string is an actual array and \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. */ /*! diff --git a/src/corelib/tools/qstringview.h b/src/corelib/tools/qstringview.h index 1eb267f78e..acf05a909c 100644 --- a/src/corelib/tools/qstringview.h +++ b/src/corelib/tools/qstringview.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE # ifndef QT_UNICODE_LITERAL # error "If you change QStringLiteral, please change QStringViewLiteral, too" # endif -# define QStringViewLiteral(str) QStringView(QT_UNICODE_LITERAL(str), sizeof(str) - 1) +# define QStringViewLiteral(str) QStringView(QT_UNICODE_LITERAL(str)) #endif namespace QtPrivate { @@ -69,6 +69,24 @@ template struct IsCompatibleCharType : IsCompatibleCharTypeHelper::type>::type> {}; +template +struct IsCompatibleArrayHelper : std::false_type {}; +template +struct IsCompatibleArrayHelper + : IsCompatibleCharType {}; +template +struct IsCompatibleArray + : IsCompatibleArrayHelper::type>::type> {}; + +template +struct IsCompatiblePointerHelper : std::false_type {}; +template +struct IsCompatiblePointerHelper + : IsCompatibleCharType {}; +template +struct IsCompatiblePointer + : IsCompatiblePointerHelper::type>::type> {}; + template struct IsCompatibleStdBasicStringHelper : std::false_type {}; template @@ -108,21 +126,32 @@ private: template using if_compatible_char = typename std::enable_if::value, bool>::type; + template + using if_compatible_array = typename std::enable_if::value, bool>::type; + + template + using if_compatible_pointer = typename std::enable_if::value, bool>::type; + template using if_compatible_string = typename std::enable_if::value, bool>::type; template using if_compatible_qstring_like = typename std::enable_if::value || std::is_same::value, bool>::type; + template + static Q_DECL_CONSTEXPR size_type lengthHelperArray(const Char (&)[N]) Q_DECL_NOTHROW + { + return size_type(N - 1); + } template - static Q_DECL_RELAXED_CONSTEXPR size_type lengthHelper(const Char *str) Q_DECL_NOTHROW + static Q_DECL_RELAXED_CONSTEXPR size_type lengthHelperPointer(const Char *str) Q_DECL_NOTHROW { size_type result = 0; while (*str++) ++result; return result; } - static Q_DECL_RELAXED_CONSTEXPR size_type lengthHelper(const QChar *str) Q_DECL_NOTHROW + static Q_DECL_RELAXED_CONSTEXPR size_type lengthHelperPointer(const QChar *str) Q_DECL_NOTHROW { size_type result = 0; while (!str++->isNull()) @@ -151,9 +180,21 @@ public: : m_size((Q_ASSERT(len >= 0), Q_ASSERT(str || !len), len)), m_data(castHelper(str)) {} - template = true> - Q_DECL_CONSTEXPR QStringView(const Char *str) - : QStringView(str, str ? lengthHelper(str) : 0) {} +#ifdef Q_QDOC + template + Q_DECL_CONSTEXPR QStringView(const Char (&array)[N]) Q_DECL_NOTHROW; + + template + Q_DECL_CONSTEXPR QStringView(const Char *str) Q_DECL_NOTHROW; +#else + template = true> + Q_DECL_CONSTEXPR QStringView(const Array &str) Q_DECL_NOTHROW + : QStringView(str, lengthHelperArray(str)) {} + + template = true> + Q_DECL_CONSTEXPR QStringView(const Pointer &str) Q_DECL_NOTHROW + : QStringView(str, str ? lengthHelperPointer(str) : 0) {} +#endif #ifdef Q_QDOC QStringView(const QString &str) Q_DECL_NOTHROW; diff --git a/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp b/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp index 433ba9cec6..2c06905d7b 100644 --- a/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp +++ b/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp @@ -58,6 +58,8 @@ Q_STATIC_ASSERT(!CanConvert::value); Q_STATIC_ASSERT(!CanConvert::value); +Q_STATIC_ASSERT(CanConvert::value); + Q_STATIC_ASSERT(CanConvert< QString >::value); Q_STATIC_ASSERT(CanConvert::value); Q_STATIC_ASSERT(CanConvert< QString&>::value); @@ -75,6 +77,8 @@ Q_STATIC_ASSERT(CanConvert::value); Q_STATIC_ASSERT(!CanConvert::value); +Q_STATIC_ASSERT(CanConvert::value); + Q_STATIC_ASSERT(CanConvert< ushort*>::value); Q_STATIC_ASSERT(CanConvert::value); @@ -232,6 +236,43 @@ void tst_QStringView::constExpr() const Q_STATIC_ASSERT(sv.back() == QLatin1Char('o')); Q_STATIC_ASSERT(sv.last() == QLatin1Char('o')); } +#if !defined(Q_OS_WIN) || defined(Q_COMPILER_UNICODE_STRINGS) + { + Q_STATIC_ASSERT(QStringView(u"Hello").size() == 5); + constexpr QStringView sv = u"Hello"; + Q_STATIC_ASSERT(sv.size() == 5); + Q_STATIC_ASSERT(!sv.empty()); + Q_STATIC_ASSERT(!sv.isEmpty()); + Q_STATIC_ASSERT(!sv.isNull()); + Q_STATIC_ASSERT(*sv.utf16() == 'H'); + Q_STATIC_ASSERT(sv[0] == QLatin1Char('H')); + Q_STATIC_ASSERT(sv.at(0) == QLatin1Char('H')); + Q_STATIC_ASSERT(sv.front() == QLatin1Char('H')); + Q_STATIC_ASSERT(sv.first() == QLatin1Char('H')); + Q_STATIC_ASSERT(sv[4] == QLatin1Char('o')); + Q_STATIC_ASSERT(sv.at(4) == QLatin1Char('o')); + Q_STATIC_ASSERT(sv.back() == QLatin1Char('o')); + Q_STATIC_ASSERT(sv.last() == QLatin1Char('o')); + } +#else // storage_type is wchar_t + { + Q_STATIC_ASSERT(QStringView(L"Hello").size() == 5); + constexpr QStringView sv = L"Hello"; + Q_STATIC_ASSERT(sv.size() == 5); + Q_STATIC_ASSERT(!sv.empty()); + Q_STATIC_ASSERT(!sv.isEmpty()); + Q_STATIC_ASSERT(!sv.isNull()); + Q_STATIC_ASSERT(*sv.utf16() == 'H'); + Q_STATIC_ASSERT(sv[0] == QLatin1Char('H')); + Q_STATIC_ASSERT(sv.at(0) == QLatin1Char('H')); + Q_STATIC_ASSERT(sv.front() == QLatin1Char('H')); + Q_STATIC_ASSERT(sv.first() == QLatin1Char('H')); + Q_STATIC_ASSERT(sv[4] == QLatin1Char('o')); + Q_STATIC_ASSERT(sv.at(4) == QLatin1Char('o')); + Q_STATIC_ASSERT(sv.back() == QLatin1Char('o')); + Q_STATIC_ASSERT(sv.last() == QLatin1Char('o')); + } +#endif #endif }