diff options
Diffstat (limited to 'src/corelib/global/qttypetraits.qdoc')
-rw-r--r-- | src/corelib/global/qttypetraits.qdoc | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/src/corelib/global/qttypetraits.qdoc b/src/corelib/global/qttypetraits.qdoc new file mode 100644 index 0000000000..ed814d6f43 --- /dev/null +++ b/src/corelib/global/qttypetraits.qdoc @@ -0,0 +1,146 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \headerfile <QtTypeTraits> + \inmodule QtCore + \since 6.5 + \title Qt Type Traits + \brief Functionality for type traits and transformations. +*/ + +/*! + \fn template <typename Enum> std::underlying_type_t<Enum> qToUnderlying(Enum e) + \relates <QtTypeTraits> + \since 6.2 + + Converts the enumerator \a e to the equivalent value expressed in its + enumeration's underlying type. +*/ + +/*! + \fn template <typename T> typename std::add_const<T>::type &qAsConst(T &t) + \relates <QtTypeTraits> + \since 5.7 + + \deprecated [6.6] Use std::as_const() instead. + + Returns \a t cast to \c{const T}. + + This function is a Qt implementation of C++17's std::as_const(), + a cast function like std::move(). But while std::move() turns + lvalues into rvalues, this function turns non-const lvalues into + const lvalues. Like std::as_const(), it doesn't work on rvalues, + because it cannot be efficiently implemented for rvalues without + leaving dangling references. + + Its main use in Qt is to prevent implicitly-shared Qt containers + from detaching: + \snippet code/src_corelib_global_qglobal.cpp as-const-0 + + Of course, in this case, you could (and probably should) have declared + \c s as \c const in the first place: + \snippet code/src_corelib_global_qglobal.cpp as-const-1 + but often that is not easily possible. + + It is important to note that qAsConst() does not copy its argument, + it just performs a \c{const_cast<const T&>(t)}. This is also the reason + why it is designed to fail for rvalues: The returned reference would go + stale too soon. So while this works (but detaches the returned object): + \snippet code/src_corelib_global_qglobal.cpp as-const-2 + + this would not: + \snippet code/src_corelib_global_qglobal.cpp as-const-3 + + To prevent this construct from compiling (and failing at runtime), qAsConst() has + a second, deleted, overload which binds to rvalues. + + \note You can make the qAsConst() function unavailable by defining + the \l{QT_NO_QASCONST} macro. +*/ + +/*! + \macro QT_NO_QASCONST + \since 6.8 + \relates <QtTypeTraits> + + Defining this macro removes the availability of the qAsConst() + function. + + \sa qAsConst +*/ + +/*! + \fn template <typename T> void qAsConst(const T &&t) + \relates <QtTypeTraits> + \since 5.7 + \overload + + \deprecated [6.6] + + This overload is deleted to prevent a dangling reference in code like + \snippet code/src_corelib_global_qglobal.cpp as-const-4 +*/ + +/*! + \fn template <typename T, typename U = T> T qExchange(T &obj, U &&newValue) + \relates <QtTypeTraits> + \since 5.14 + + Replaces the value of \a obj with \a newValue and returns the old value of \a obj. + + This is Qt's implementation of std::exchange(). It differs from std::exchange() + only in that it is \c constexpr already before C++20 and noexcept already before C++23. + + We strongly advise to use std::exchange() when you don't need the C++20 or C++23 variants. + You can make qExchange() unavailable by defining the \l{QT_NO_QEXCHANGE} macro. + + Here is how to use qExchange() to implement move constructors: + \code + MyClass(MyClass &&other) + : m_pointer{qExchange(other.m_pointer, nullptr)}, + m_int{qExchange(other.m_int, 0)}, + m_vector{std::move(other.m_vector)}, + ... + \endcode + + For members of class type, we can use std::move(), as their move-constructor will + do the right thing. But for scalar types such as raw pointers or integer type, move + is the same as copy, which, particularly for pointers, is not what we expect. So, we + cannot use std::move() for such types, but we can use std::exchange()/qExchange() to + make sure the source object's member is already reset by the time we get to the + initialization of our next data member, which might come in handy if the constructor + exits with an exception. + + Here is how to use qExchange() to write a loop that consumes the collection it + iterates over: + \code + for (auto &e : qExchange(collection, {}) + doSomethingWith(e); + \endcode + + Which is equivalent to the following, much more verbose code: + \code + { + auto tmp = std::move(collection); + collection = {}; // or collection.clear() + for (auto &e : tmp) + doSomethingWith(e); + } // destroys 'tmp' + \endcode + + This is perfectly safe, as the for-loop keeps the result of qExchange() alive for as + long as the loop runs, saving the declaration of a temporary variable. Be aware, though, + that qExchange() returns a non-const object, so Qt containers may detach. +*/ + +/*! + \macro QT_NO_QEXCHANGE + \since 6.6 + \relates <QtTypeTraits> + + Defining this macro removes the availability of the qExchange() + function. + + \sa qExchange +*/ |