diff options
author | Marc Mutz <marc.mutz@qt.io> | 2023-06-02 16:22:37 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2023-06-07 23:18:03 +0000 |
commit | f5ed163c19c4a165a61e6fbfdaf5ee39b5587a0c (patch) | |
tree | a8ab795999c4e6ec4bdc91ca26167564f6433cb6 /src/corelib/text/qstring.h | |
parent | 245c2b621f5942861b7f827bfc8a859b9efb9b72 (diff) |
QString: add STL-style assign() [2/4]: (it,it) overload for QChar-convertible *it
Restrict the permissible value_types to those QStringView can take,
plus QLatin1Char. All of these implicitly convert to QChar and give
the correct result, even when converted char-by-char.
Task-number: QTBUG-106198
Pick-to: 6.6
Change-Id: Icb44244cb08af391161c4309467d4e0d2d3d3d62
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Dennis Oberst <dennis.oberst@qt.io>
Diffstat (limited to 'src/corelib/text/qstring.h')
-rw-r--r-- | src/corelib/text/qstring.h | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h index 71b712c3e9..76833147d4 100644 --- a/src/corelib/text/qstring.h +++ b/src/corelib/text/qstring.h @@ -24,6 +24,7 @@ #include <string> #include <iterator> +#include <QtCore/q20memory.h> #include <stdarg.h> @@ -120,6 +121,33 @@ class Q_CORE_EXPORT QString typedef QTypedArrayData<char16_t> Data; friend class ::tst_QString; + + template <typename Iterator> + static constexpr bool is_contiguous_iterator_v = + // Can't use contiguous_iterator_tag here, as STL impls can't agree on feature macro. + // To avoid differences in C++20 and C++17 builds, treat only pointers as contiguous + // for now: + // std::contiguous_iterator<Iterator>; + std::is_pointer_v<Iterator>; + + template <typename Char> + using is_compatible_char_helper = std::disjunction< + QtPrivate::IsCompatibleCharType<Char>, + std::is_same<Char, QLatin1Char> // special case + >; + + template <typename Iterator> + static constexpr bool is_compatible_iterator_v = std::conjunction_v< + std::is_convertible< + typename std::iterator_traits<Iterator>::iterator_category, + std::input_iterator_tag + >, + is_compatible_char_helper<typename std::iterator_traits<Iterator>::value_type> + >; + + template <typename Iterator> + using if_compatible_iterator = std::enable_if_t<is_compatible_iterator_v<Iterator>, bool>; + public: typedef QStringPrivate DataPointer; @@ -385,6 +413,26 @@ public: Q_ASSERT(n >= 0); return fill(c, n); } + template <typename InputIterator, if_compatible_iterator<InputIterator> = true> + QString &assign(InputIterator first, InputIterator last) + { + using V = typename std::iterator_traits<InputIterator>::value_type; + constexpr bool IsL1C = std::is_same_v<std::remove_cv_t<V>, QLatin1Char>; + + if constexpr (is_contiguous_iterator_v<InputIterator>) { + const auto p = q20::to_address(first); + const auto len = qsizetype(last - first); + if constexpr (IsL1C) + return assign(QLatin1StringView(reinterpret_cast<const char*>(p), len)); + else + return assign(QAnyStringView(p, len)); + } else { // non-contiguous iterator, need to feed data piecemeal + d.assign(first, last, [](QChar ch) -> char16_t { return ch.unicode(); }); + d.data()[d.size] = u'\0'; + return *this; + } + } + inline QString &operator+=(QChar c) { return append(c); } inline QString &operator+=(const QString &s) { return append(s); } |