diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2017-03-27 11:22:44 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2017-03-29 12:29:35 +0000 |
commit | 718023606370d7c0f972acb0ba83df3383b8800a (patch) | |
tree | 80f7929207bc73a1c5732d382c55cca2f1986621 /src/corelib | |
parent | e9c06b25af47e869028c7a56a679fda7b4475f38 (diff) |
QStringView: improve manual overload management
We want to prevent
QStringView(QChar|QLatin1String|QByteArray|const char*)
from compiling as QStringView(QString(...)), so I added = delete'ed
ctors for these types to QStringView. However, that makes QStringView
participate in overload resolution for these types. Even if the
QStringView ctor will always fail to compile, the presence of these
ctors alone makes calls to functions overloaded on QString and
QStringView ambiguous:
f(QStringView);
f(QString);
f(foo); // ambiguous
f(QChar('f')) // ambiguous
f(QLatin1String(foo)); // ambiguous
f(QByteArray(foo)); // ambiguous
Fix by making the QString and QStringRef constructors templates
constrained to accept only these two types. This should also help to
move the QStringView definition to before the QString one (as soon as
we get rid of or start to ignore QString::Null), simplifying a lot of
code in qstring.h down the line.
This should also fix MSVC's accepting of two user-defined conversions
which caused static non-compile-tests to fail in the initial
QStringView patch, and which were therefore removed. This patch brings
them back.
Change-Id: I95ac38c0d31cd8c726f7e952017569d32e484413
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/tools/qstringview.h | 27 |
1 files changed, 10 insertions, 17 deletions
diff --git a/src/corelib/tools/qstringview.h b/src/corelib/tools/qstringview.h index 5384e73039..b1722e4657 100644 --- a/src/corelib/tools/qstringview.h +++ b/src/corelib/tools/qstringview.h @@ -111,6 +111,9 @@ private: 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> static Q_DECL_RELAXED_CONSTEXPR size_type lengthHelper(const Char *str) Q_DECL_NOTHROW { @@ -133,20 +136,6 @@ private: static Q_DECL_CONSTEXPR const storage_type *castHelper(const storage_type *str) Q_DECL_NOTHROW { return str; } - // prevent - // T t; QStringView sv(t), T \in {QChar, QLatin1String, QByteArray, const char*} - // from compiling as QStringView sv(QString(t)): - QStringView(QChar) = delete; - QStringView(QLatin1String) = delete; - QStringView(const QByteArray &) = delete; - QStringView(const char *) = delete; - -#ifdef Q_OS_WIN - // prevent QStringView(Char), Char compatible, from compiling due to: - // https://connect.microsoft.com/VisualStudio/feedback/details/2256407/c-two-user-defined-conversions-incorrectly-accepted-in-implicit-conversion-sequence - template <typename Char, if_compatible_char<Char> = true> - QStringView(Char) = delete; -#endif public: Q_DECL_CONSTEXPR QStringView() Q_DECL_NOTHROW : m_size(0), m_data(nullptr) {} @@ -166,10 +155,14 @@ public: Q_DECL_CONSTEXPR QStringView(const Char *str) : QStringView(str, str ? lengthHelper(str) : 0) {} - QStringView(const QString &str) Q_DECL_NOTHROW - : QStringView(str.isNull() ? nullptr : str.data(), size_type(str.size())) {} - QStringView(const QStringRef &str) Q_DECL_NOTHROW +#ifdef Q_QDOC + QStringView(const QString &str) Q_DECL_NOTHROW; + QStringView(const QStringRef &str) Q_DECL_NOTHROW; +#else + template <typename String, if_compatible_qstring_like<String> = true> + QStringView(const String &str) Q_DECL_NOTHROW : QStringView(str.isNull() ? nullptr : str.data(), size_type(str.size())) {} +#endif template <typename StdBasicString, if_compatible_string<StdBasicString> = true> QStringView(const StdBasicString &str) Q_DECL_NOTHROW |