QUtf8StringView: ensure binary compatibility throughout 6.x

We can't depend on whether the user compiles with -std=c++17 or
-std=c++20. So select what we can depend on and make that permanent.

Prior to this change:

 $ cat /tmp/test.cpp
 #include <QtCore/QUtf8StringView>
 void f(QUtf8StringView) {}
 $ qcd include
 $ g++ -S -o - -I. /tmp/test.cpp | grep globl | c++filt
         .globl  f(QBasicUtf8StringView<false>)
 $ g++ -fPIC -std=c++20 -S -o - -I. /tmp/test.cpp | grep globl | c++filt
         .globl  f(QBasicUtf8StringView<true>)

After this change, they're both "false". QUtf8StringView should have
been a concrete class that derived from QBsicUtf8StringView<whichever>
and inherited all its constructors. We'd cause ODR violations in C++20,
but nothing worse than what we usually do for BC reasons.

That solution is too late for Qt 6.x. Let's revisit in 7.0.

Change-Id: I6bcbe88c072a438b8b4efffd166e77199ecb39e3
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
(cherry picked from commit c7deb3400faa1d9389137fe63ffbffade8203850)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Thiago Macieira 2021-03-21 13:57:48 -07:00 committed by Qt Cherry-pick Bot
parent e5e6ca7836
commit 9c7a811327
3 changed files with 5 additions and 32 deletions

View File

@ -48,7 +48,7 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
#ifdef __cpp_char8_t #if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
# define QT_BEGIN_HAS_CHAR8_T_NAMESPACE inline namespace q_has_char8_t { # define QT_BEGIN_HAS_CHAR8_T_NAMESPACE inline namespace q_has_char8_t {
# define QT_BEGIN_NO_CHAR8_T_NAMESPACE namespace q_no_char8_t { # define QT_BEGIN_NO_CHAR8_T_NAMESPACE namespace q_no_char8_t {
#else #else

View File

@ -359,6 +359,7 @@ private:
template <bool UseChar8T> template <bool UseChar8T>
Q_DECLARE_TYPEINFO_BODY(QBasicUtf8StringView<UseChar8T>, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO_BODY(QBasicUtf8StringView<UseChar8T>, Q_PRIMITIVE_TYPE);
// ### Qt 7: remove the non-char8_t version of QUtf8StringView
QT_BEGIN_NO_CHAR8_T_NAMESPACE QT_BEGIN_NO_CHAR8_T_NAMESPACE
using QUtf8StringView = QBasicUtf8StringView<false>; using QUtf8StringView = QBasicUtf8StringView<false>;
QT_END_NO_CHAR8_T_NAMESPACE QT_END_NO_CHAR8_T_NAMESPACE

View File

@ -116,42 +116,14 @@
The second, in namespace \c{q_has_char8_t}, has a value_type of The second, in namespace \c{q_has_char8_t}, has a value_type of
\c{const char8_t} and is only available when compiling in C++20 mode. \c{const char8_t} and is only available when compiling in C++20 mode.
In C++17 mode, \c{q_no_char8_t} is an inline namespace, in C++20 it's \c{q_no_char8_t} is an inline namespace regardless of C++ edition, to avoid
\c{q_has_char8_t}. This means that the name "QUtf8StringView" (without accidental binary incompatibilities. To use the \c{char8_t} version, you
explicit namespace) will denote different types in C++17 and C++20 modes. need to name it explicitly with \c{q_has_char8_t::QUtf8StringView}.
Internally, both are instantiations of the same template class, Internally, both are instantiations of the same template class,
QBasicUtf8StringView. Please do not use the template class's name in your QBasicUtf8StringView. Please do not use the template class's name in your
source code. source code.
All Qt APIs use \c{q_no_char8_t::QUtf8StringView} due to binary compatibility,
but these APIs accept \c{q_has_char8_t::QUtf8StringView} as well, since the
latter implicitly converts into the former, and vice versa.
In your own code, please use only \c QUtf8StringView and/or
\c{q_no_char8_t::QUtf8StringView}:
\list
\li If you only target C++20, then use "QUtf8StringView". It will be an alias
for \c{q_has_char8_t::QUtf8StringView} and you'll never look back.
\li If you only target C++17, then use "QUtf8StringView". It will be an alias
for \c{q_no_char8_t::QUtf8StringView} and for the time being, you're ok.
\li If you target both C++17 and C++20, then you have a choice to make:
\list
\li If you don't mind the source-incompatibility of return values of
QUtf8StringView::data() etc changing when compiling under C++17 or C++20,
use "QUtf8StringView". You will need to write your code in such a way that
it adapts to the differences in the QUtf8StringView API in different C++
versions.
\li If you don't want to deal with the above source-incompatibilities, or if
you need to maintain binary compatibility between C++20 and C++17 builds,
use "q_no_char8_t::QUtf8StringView" explicitly. Be aware that the
\c{q_no_char8_t} version will disappear in Qt 7.
\endlist
\endlist
Taken together: Just use QUtf8StringView unless you know what you're doing.
\sa QAnyStringView, QUtf8StringView, QString \sa QAnyStringView, QUtf8StringView, QString
*/ */