Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qttypetraits.qdoc
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4/*!
5 \headerfile <QtTypeTraits>
6 \inmodule QtCore
7 \since 6.5
8 \title Qt Type Traits
9 \brief Functionality for type traits and transformations.
10*/
11
12/*!
13 \fn template <typename Enum> std::underlying_type_t<Enum> qToUnderlying(Enum e)
14 \relates <QtTypeTraits>
15 \since 6.2
16
17 Converts the enumerator \a e to the equivalent value expressed in its
18 enumeration's underlying type.
19*/
20
21/*!
22 \fn template <typename T> typename std::add_const<T>::type &qAsConst(T &t)
23 \relates <QtTypeTraits>
24 \since 5.7
25
26 \deprecated [6.6] Use std::as_const() instead.
27
28 Returns \a t cast to \c{const T}.
29
30 This function is a Qt implementation of C++17's std::as_const(),
31 a cast function like std::move(). But while std::move() turns
32 lvalues into rvalues, this function turns non-const lvalues into
33 const lvalues. Like std::as_const(), it doesn't work on rvalues,
34 because it cannot be efficiently implemented for rvalues without
35 leaving dangling references.
36
37 Its main use in Qt is to prevent implicitly-shared Qt containers
38 from detaching:
39 \snippet code/src_corelib_global_qglobal.cpp as-const-0
40
41 Of course, in this case, you could (and probably should) have declared
42 \c s as \c const in the first place:
43 \snippet code/src_corelib_global_qglobal.cpp as-const-1
44 but often that is not easily possible.
45
46 It is important to note that qAsConst() does not copy its argument,
47 it just performs a \c{const_cast<const T&>(t)}. This is also the reason
48 why it is designed to fail for rvalues: The returned reference would go
49 stale too soon. So while this works (but detaches the returned object):
50 \snippet code/src_corelib_global_qglobal.cpp as-const-2
51
52 this would not:
53 \snippet code/src_corelib_global_qglobal.cpp as-const-3
54
55 To prevent this construct from compiling (and failing at runtime), qAsConst() has
56 a second, deleted, overload which binds to rvalues.
57
58 \note You can make the qAsConst() function unavailable by defining
59 the \l{QT_NO_QASCONST} macro.
60*/
61
62/*!
63 \macro QT_NO_QASCONST
64 \since 6.8
65 \relates <QtTypeTraits>
66
67 Defining this macro removes the availability of the qAsConst()
68 function.
69
70 \sa qAsConst
71*/
72
73/*!
74 \fn template <typename T> void qAsConst(const T &&t)
75 \relates <QtTypeTraits>
76 \since 5.7
77 \overload
78
79 \deprecated [6.6]
80
81 This overload is deleted to prevent a dangling reference in code like
82 \snippet code/src_corelib_global_qglobal.cpp as-const-4
83*/
84
85/*!
86 \fn template <typename T, typename U = T> T qExchange(T &obj, U &&newValue)
87 \relates <QtTypeTraits>
88 \since 5.14
89
90 Replaces the value of \a obj with \a newValue and returns the old value of \a obj.
91
92 This is Qt's implementation of std::exchange(). It differs from std::exchange()
93 only in that it is \c constexpr already before C++20 and noexcept already before C++23.
94
95 We strongly advise to use std::exchange() when you don't need the C++20 or C++23 variants.
96 You can make qExchange() unavailable by defining the \l{QT_NO_QEXCHANGE} macro.
97
98 Here is how to use qExchange() to implement move constructors:
99 \code
100 MyClass(MyClass &&other)
101 : m_pointer{qExchange(other.m_pointer, nullptr)},
102 m_int{qExchange(other.m_int, 0)},
103 m_vector{std::move(other.m_vector)},
104 ...
105 \endcode
106
107 For members of class type, we can use std::move(), as their move-constructor will
108 do the right thing. But for scalar types such as raw pointers or integer type, move
109 is the same as copy, which, particularly for pointers, is not what we expect. So, we
110 cannot use std::move() for such types, but we can use std::exchange()/qExchange() to
111 make sure the source object's member is already reset by the time we get to the
112 initialization of our next data member, which might come in handy if the constructor
113 exits with an exception.
114
115 Here is how to use qExchange() to write a loop that consumes the collection it
116 iterates over:
117 \code
118 for (auto &e : qExchange(collection, {})
119 doSomethingWith(e);
120 \endcode
121
122 Which is equivalent to the following, much more verbose code:
123 \code
124 {
125 auto tmp = std::move(collection);
126 collection = {}; // or collection.clear()
127 for (auto &e : tmp)
128 doSomethingWith(e);
129 } // destroys 'tmp'
130 \endcode
131
132 This is perfectly safe, as the for-loop keeps the result of qExchange() alive for as
133 long as the loop runs, saving the declaration of a temporary variable. Be aware, though,
134 that qExchange() returns a non-const object, so Qt containers may detach.
135*/
136
137/*!
138 \macro QT_NO_QEXCHANGE
139 \since 6.6
140 \relates <QtTypeTraits>
141
142 Defining this macro removes the availability of the qExchange()
143 function.
144
145 \sa qExchange
146*/