diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2022-09-30 13:12:42 +0200 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2022-10-06 14:26:24 +0200 |
commit | dff985140a9f31632ba6630ec3391be55051a7ac (patch) | |
tree | 380babdac720c2cec4d10f493edf95581c4791d3 /src/corelib/global/qglobal.cpp | |
parent | 394e9a8d06e475a46d6e14cc96dfd12d431cb412 (diff) |
Move qAsConst() and qExchange() to QtTypeTraits
It's the least worst place we could think of.
Add the qttypetraits.h include to qforeach, because otherwise
the tests fail to build.
Task-number: QTBUG-106154
Task-number: QTBUG-99313
Change-Id: I841f22e887f351146589377ec2376957e2adfd5e
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/global/qglobal.cpp')
-rw-r--r-- | src/corelib/global/qglobal.cpp | 96 |
1 files changed, 0 insertions, 96 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 7077efb662..e444755f1b 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -228,102 +228,6 @@ void qAbort() // strftime() -- not used (except in tests) /*! - \fn template <typename T> typename std::add_const<T>::type &qAsConst(T &t) - \relates <QtGlobal> - \since 5.7 - - 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. -*/ - -/*! - \fn template <typename T> void qAsConst(const T &&t) - \relates <QtGlobal> - \since 5.7 - \overload - - 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 <QtGlobal> - \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 in C++14, and available on all supported - compilers. - - 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 Q_UNUSED(name) \relates <QtGlobal> |