QStringView: add an array ctor
With sufficient enable_if magic, the array ctor can overload the pointer ctor and statically determine the size of the array passed. Consequently, remove the sizeof in QStringViewLiteral again. Change-Id: I486baa3cafefde60ccc5f2b47eb94ee53cefe63c Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
d40dcee642
commit
8b5aa7b6c4
@ -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.
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
@ -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 <typename Char>
|
||||
struct IsCompatibleCharType
|
||||
: IsCompatibleCharTypeHelper<typename std::remove_cv<typename std::remove_reference<Char>::type>::type> {};
|
||||
|
||||
template <typename Array>
|
||||
struct IsCompatibleArrayHelper : std::false_type {};
|
||||
template <typename Char, size_t N>
|
||||
struct IsCompatibleArrayHelper<Char[N]>
|
||||
: IsCompatibleCharType<Char> {};
|
||||
template <typename Array>
|
||||
struct IsCompatibleArray
|
||||
: IsCompatibleArrayHelper<typename std::remove_cv<typename std::remove_reference<Array>::type>::type> {};
|
||||
|
||||
template <typename Pointer>
|
||||
struct IsCompatiblePointerHelper : std::false_type {};
|
||||
template <typename Char>
|
||||
struct IsCompatiblePointerHelper<Char*>
|
||||
: IsCompatibleCharType<Char> {};
|
||||
template <typename Pointer>
|
||||
struct IsCompatiblePointer
|
||||
: IsCompatiblePointerHelper<typename std::remove_cv<typename std::remove_reference<Pointer>::type>::type> {};
|
||||
|
||||
template <typename T>
|
||||
struct IsCompatibleStdBasicStringHelper : std::false_type {};
|
||||
template <typename Char, typename...Args>
|
||||
@ -108,21 +126,32 @@ private:
|
||||
template <typename Char>
|
||||
using if_compatible_char = typename std::enable_if<QtPrivate::IsCompatibleCharType<Char>::value, bool>::type;
|
||||
|
||||
template <typename Array>
|
||||
using if_compatible_array = typename std::enable_if<QtPrivate::IsCompatibleArray<Array>::value, bool>::type;
|
||||
|
||||
template <typename Pointer>
|
||||
using if_compatible_pointer = typename std::enable_if<QtPrivate::IsCompatiblePointer<Pointer>::value, bool>::type;
|
||||
|
||||
template <typename T>
|
||||
using if_compatible_string = typename std::enable_if<QtPrivate::IsCompatibleStdBasicString<T>::value, bool>::type;
|
||||
|
||||
template <typename T>
|
||||
using if_compatible_qstring_like = typename std::enable_if<std::is_same<T, QString>::value || std::is_same<T, QStringRef>::value, bool>::type;
|
||||
|
||||
template <typename Char, size_t N>
|
||||
static Q_DECL_CONSTEXPR size_type lengthHelperArray(const Char (&)[N]) Q_DECL_NOTHROW
|
||||
{
|
||||
return size_type(N - 1);
|
||||
}
|
||||
template <typename Char>
|
||||
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 <typename Char, if_compatible_char<Char> = true>
|
||||
Q_DECL_CONSTEXPR QStringView(const Char *str)
|
||||
: QStringView(str, str ? lengthHelper(str) : 0) {}
|
||||
#ifdef Q_QDOC
|
||||
template <typename Char, size_t N>
|
||||
Q_DECL_CONSTEXPR QStringView(const Char (&array)[N]) Q_DECL_NOTHROW;
|
||||
|
||||
template <typename Char>
|
||||
Q_DECL_CONSTEXPR QStringView(const Char *str) Q_DECL_NOTHROW;
|
||||
#else
|
||||
template <typename Array, if_compatible_array<Array> = true>
|
||||
Q_DECL_CONSTEXPR QStringView(const Array &str) Q_DECL_NOTHROW
|
||||
: QStringView(str, lengthHelperArray(str)) {}
|
||||
|
||||
template <typename Pointer, if_compatible_pointer<Pointer> = 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;
|
||||
|
@ -58,6 +58,8 @@ Q_STATIC_ASSERT(!CanConvert<QByteArray>::value);
|
||||
|
||||
Q_STATIC_ASSERT(!CanConvert<QChar>::value);
|
||||
|
||||
Q_STATIC_ASSERT(CanConvert<QChar[123]>::value);
|
||||
|
||||
Q_STATIC_ASSERT(CanConvert< QString >::value);
|
||||
Q_STATIC_ASSERT(CanConvert<const QString >::value);
|
||||
Q_STATIC_ASSERT(CanConvert< QString&>::value);
|
||||
@ -75,6 +77,8 @@ Q_STATIC_ASSERT(CanConvert<const QStringRef&>::value);
|
||||
|
||||
Q_STATIC_ASSERT(!CanConvert<ushort>::value);
|
||||
|
||||
Q_STATIC_ASSERT(CanConvert<ushort[123]>::value);
|
||||
|
||||
Q_STATIC_ASSERT(CanConvert< ushort*>::value);
|
||||
Q_STATIC_ASSERT(CanConvert<const ushort*>::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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user