Extend QString::arg(QString, ..., QString) to more than 9 arguments

Now that we have QStringView::arg(), we can use it to implement a
similarly flexible QString::arg(). It's not as straight-forward as in
QStringView, though: QString has existing arg() overloads that all
become worse matches with the introduction of the new,
perfectly-forwarding overload.

So in order to allow calling of the other arg() functions, first
constrain the new arg() function to arguments that are convertible to
QString, QStringView, or QLatin1String, and then delegate to the
QStringView version. To stay compatible with the previous overloads,
which accepted anything that implicitly converts to QString (in
particular, QStringBuilder expressions), add a new overload of
qStringLikeToView, taking const QString &. This benefits the existing
QStringView and QLatin1View versions, too.

[ChangeLog][QtCore][QString] QString::arg(QString, ..., QString) can
now be called with more than nine arguments, as well as with
QStringViews.

Change-Id: I1e717a1bc696346808bcae45dc47762a492c8714
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Marc Mutz 2017-01-07 21:58:01 +01:00
parent ca5fc087bd
commit fd42589b14
2 changed files with 38 additions and 2 deletions

View File

@ -89,6 +89,10 @@ class QTextCodec;
class QStringRef;
template <typename T> class QVector;
namespace QtPrivate {
template <bool...B> class BoolList;
}
class QLatin1String
{
public:
@ -333,6 +337,7 @@ public:
QChar fillChar = QLatin1Char(' ')) const;
Q_REQUIRED_RESULT QString arg(QLatin1String a, int fieldWidth = 0,
QChar fillChar = QLatin1Char(' ')) const;
#if QT_STRINGVIEW_LEVEL < 2
Q_REQUIRED_RESULT QString arg(const QString &a1, const QString &a2) const;
Q_REQUIRED_RESULT QString arg(const QString &a1, const QString &a2, const QString &a3) const;
Q_REQUIRED_RESULT QString arg(const QString &a1, const QString &a2, const QString &a3,
@ -350,6 +355,33 @@ public:
Q_REQUIRED_RESULT QString arg(const QString &a1, const QString &a2, const QString &a3,
const QString &a4, const QString &a5, const QString &a6,
const QString &a7, const QString &a8, const QString &a9) const;
#endif
private:
template <typename T>
struct is_convertible_to_view_or_qstring_helper
: std::integral_constant<bool,
std::is_convertible<T, QString>::value ||
std::is_convertible<T, QStringView>::value ||
std::is_convertible<T, QLatin1String>::value> {};
template <typename T>
struct is_convertible_to_view_or_qstring
: is_convertible_to_view_or_qstring_helper<typename std::decay<T>::type> {};
public:
template <typename...Args>
Q_REQUIRED_RESULT
#ifdef Q_CLANG_QDOC
QString
#else
typename std::enable_if<
sizeof...(Args) >= 2 && std::is_same<
QtPrivate::BoolList<is_convertible_to_view_or_qstring<Args>::value..., true>,
QtPrivate::BoolList<true, is_convertible_to_view_or_qstring<Args>::value...>
>::value,
QString
>::type
#endif
arg(Args &&...args) const
{ return qToStringViewIgnoringNull(*this).arg(std::forward<Args>(args)...); }
#if QT_DEPRECATED_SINCE(5, 14)
QT_DEPRECATED_X("Use vasprintf(), arg() or QTextStream instead")
@ -1053,6 +1085,7 @@ inline QString QString::arg(short a, int fieldWidth, int base, QChar fillChar) c
{ return arg(qlonglong(a), fieldWidth, base, fillChar); }
inline QString QString::arg(ushort a, int fieldWidth, int base, QChar fillChar) const
{ return arg(qulonglong(a), fieldWidth, base, fillChar); }
#if QT_STRINGVIEW_LEVEL < 2
inline QString QString::arg(const QString &a1, const QString &a2) const
{ return qToStringViewIgnoringNull(*this).arg(a1, a2); }
inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3) const
@ -1078,6 +1111,7 @@ inline QString QString::arg(const QString &a1, const QString &a2, const QString
const QString &a4, const QString &a5, const QString &a6,
const QString &a7, const QString &a8, const QString &a9) const
{ return qToStringViewIgnoringNull(*this).arg(a1, a2, a3, a4, a5, a6, a7, a8, a9); }
#endif
inline QString QString::section(QChar asep, int astart, int aend, SectionFlags aflags) const
{ return section(QString(asep), astart, aend, aflags); }
@ -2014,6 +2048,7 @@ Q_REQUIRED_RESULT Q_ALWAYS_INLINE QString argToQStringDispatch(StringView patter
return QtPrivate::argToQString(pattern, sizeof...(Args), argBases);
}
inline QStringViewArg qStringLikeToArg(const QString &s) noexcept { return QStringViewArg{qToStringViewIgnoringNull(s)}; }
Q_DECL_CONSTEXPR inline QStringViewArg qStringLikeToArg(QStringView s) noexcept { return QStringViewArg{s}; }
inline QStringViewArg qStringLikeToArg(const QChar &c) noexcept { return QStringViewArg{QStringView{&c, 1}}; }
Q_DECL_CONSTEXPR inline QLatin1StringArg qStringLikeToArg(QLatin1String s) noexcept { return QLatin1StringArg{s}; }

View File

@ -532,6 +532,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn QString QStringView::arg(Args &&...args) const
\fn QString QLatin1String::arg(Args &&...args) const
\fn QString QString::arg(Args &&...args) const
\since 5.14
Replaces occurrences of \c{%N} in this string with the corresponding
@ -539,8 +540,8 @@ QT_BEGIN_NAMESPACE
the \a args replaces the \c{%N} with the lowest \c{N} (all of them), the
second of the \a args the \c{%N} with the next-lowest \c{N} etc.
\c Args can consist of anything that implicitly converts to QStringView
or QLatin1String.
\c Args can consist of anything that implicitly converts to QString,
QStringView or QLatin1String.
In addition, the following types are also supported: QChar, QLatin1Char.