Extract header qtclasshelpermacros.h
Move the class helper macros from qglobal.h and Q_DECLARE_SHARED from qtypeinfo.h there. Task-number: QTBUG-99313 Change-Id: I8c8b6241a76916176a48c09fbaf4effc87683770 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
This commit is contained in:
parent
23ecaf897f
commit
c201c5aedf
@ -74,6 +74,7 @@ qt_internal_add_module(Core
|
|||||||
global/qrandom.cpp global/qrandom.h global/qrandom_p.h
|
global/qrandom.cpp global/qrandom.h global/qrandom_p.h
|
||||||
global/qsysinfo.h
|
global/qsysinfo.h
|
||||||
global/qsystemdetection.h
|
global/qsystemdetection.h
|
||||||
|
global/qtclasshelpermacros.h
|
||||||
global/qtconfigmacros.h
|
global/qtconfigmacros.h
|
||||||
global/qtdeprecationmarkers.h
|
global/qtdeprecationmarkers.h
|
||||||
global/qtrace_p.h
|
global/qtrace_p.h
|
||||||
|
@ -511,63 +511,6 @@ using namespace Qt::StringLiterals;
|
|||||||
(bitmask).
|
(bitmask).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
|
||||||
\macro Q_DISABLE_COPY(Class)
|
|
||||||
\relates QObject
|
|
||||||
|
|
||||||
Disables the use of copy constructors and assignment operators
|
|
||||||
for the given \a Class.
|
|
||||||
|
|
||||||
Instances of subclasses of QObject should not be thought of as
|
|
||||||
values that can be copied or assigned, but as unique identities.
|
|
||||||
This means that when you create your own subclass of QObject
|
|
||||||
(director or indirect), you should \e not give it a copy constructor
|
|
||||||
or an assignment operator. However, it may not enough to simply
|
|
||||||
omit them from your class, because, if you mistakenly write some code
|
|
||||||
that requires a copy constructor or an assignment operator (it's easy
|
|
||||||
to do), your compiler will thoughtfully create it for you. You must
|
|
||||||
do more.
|
|
||||||
|
|
||||||
The curious user will have seen that the Qt classes derived
|
|
||||||
from QObject typically include this macro in a private section:
|
|
||||||
|
|
||||||
\snippet code/src_corelib_global_qglobal.cpp 43
|
|
||||||
|
|
||||||
It declares a copy constructor and an assignment operator in the
|
|
||||||
private section, so that if you use them by mistake, the compiler
|
|
||||||
will report an error.
|
|
||||||
|
|
||||||
\snippet code/src_corelib_global_qglobal.cpp 44
|
|
||||||
|
|
||||||
But even this might not catch absolutely every case. You might be
|
|
||||||
tempted to do something like this:
|
|
||||||
|
|
||||||
\snippet code/src_corelib_global_qglobal.cpp 45
|
|
||||||
|
|
||||||
First of all, don't do that. Most compilers will generate code that
|
|
||||||
uses the copy constructor, so the privacy violation error will be
|
|
||||||
reported, but your C++ compiler is not required to generate code for
|
|
||||||
this statement in a specific way. It could generate code using
|
|
||||||
\e{neither} the copy constructor \e{nor} the assignment operator we
|
|
||||||
made private. In that case, no error would be reported, but your
|
|
||||||
application would probably crash when you called a member function
|
|
||||||
of \c{w}.
|
|
||||||
|
|
||||||
\sa Q_DISABLE_COPY_MOVE
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\macro Q_DISABLE_COPY_MOVE(Class)
|
|
||||||
\relates QObject
|
|
||||||
|
|
||||||
A convenience macro that disables the use of copy constructors, assignment
|
|
||||||
operators, move constructors and move assignment operators for the given
|
|
||||||
\a Class.
|
|
||||||
|
|
||||||
\sa Q_DISABLE_COPY
|
|
||||||
\since 5.13
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\macro Q_DECLARE_FLAGS(Flags, Enum)
|
\macro Q_DECLARE_FLAGS(Flags, Enum)
|
||||||
\relates QFlags
|
\relates QFlags
|
||||||
|
@ -46,6 +46,7 @@ inline void qt_noop(void) {}
|
|||||||
|
|
||||||
#include <QtCore/qassert.h>
|
#include <QtCore/qassert.h>
|
||||||
#include <QtCore/qtypes.h>
|
#include <QtCore/qtypes.h>
|
||||||
|
#include <QtCore/qtclasshelpermacros.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Avoid "unused parameter" warnings
|
Avoid "unused parameter" warnings
|
||||||
@ -55,65 +56,6 @@ inline void qt_noop(void) {}
|
|||||||
#ifndef __ASSEMBLER__
|
#ifndef __ASSEMBLER__
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
/*
|
|
||||||
Some classes do not permit copies to be made of an object. These
|
|
||||||
classes contains a private copy constructor and assignment
|
|
||||||
operator to disable copying (the compiler gives an error message).
|
|
||||||
*/
|
|
||||||
#define Q_DISABLE_COPY(Class) \
|
|
||||||
Class(const Class &) = delete;\
|
|
||||||
Class &operator=(const Class &) = delete;
|
|
||||||
|
|
||||||
#define Q_DISABLE_COPY_MOVE(Class) \
|
|
||||||
Q_DISABLE_COPY(Class) \
|
|
||||||
Class(Class &&) = delete; \
|
|
||||||
Class &operator=(Class &&) = delete;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Implementing a move assignment operator using an established
|
|
||||||
technique (move-and-swap, pure swap) is just boilerplate.
|
|
||||||
Here's a couple of *private* macros for convenience.
|
|
||||||
|
|
||||||
To know which one to use:
|
|
||||||
|
|
||||||
* if you don't have a move constructor (*) => use pure swap;
|
|
||||||
* if you have a move constructor, then
|
|
||||||
* if your class holds just memory (no file handles, no user-defined
|
|
||||||
datatypes, etc.) => use pure swap;
|
|
||||||
* use move and swap.
|
|
||||||
|
|
||||||
The preference should always go for the move-and-swap one, as it
|
|
||||||
will deterministically destroy the data previously held in *this,
|
|
||||||
and not "dump" it in the moved-from object (which may then be alive
|
|
||||||
for longer).
|
|
||||||
|
|
||||||
The requirement for either macro is the presence of a member swap(),
|
|
||||||
which any value class that defines its own special member functions
|
|
||||||
should have anyhow.
|
|
||||||
|
|
||||||
(*) Many value classes in Qt do not have move constructors; mostly,
|
|
||||||
the implicitly shared classes using QSharedDataPointer and friends.
|
|
||||||
The reason is mostly historical: those classes require either an
|
|
||||||
out-of-line move constructor, which we could not provide before we
|
|
||||||
made C++11 mandatory (and that we don't like anyhow), or
|
|
||||||
an out-of-line dtor for the Q(E)DSP<Private> member (cf. QPixmap).
|
|
||||||
|
|
||||||
If you can however add a move constructor to a class lacking it,
|
|
||||||
consider doing so, then reevaluate which macro to choose.
|
|
||||||
*/
|
|
||||||
#define QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(Class) \
|
|
||||||
Class &operator=(Class &&other) noexcept { \
|
|
||||||
Class moved(std::move(other)); \
|
|
||||||
swap(moved); \
|
|
||||||
return *this; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Class) \
|
|
||||||
Class &operator=(Class &&other) noexcept { \
|
|
||||||
swap(other); \
|
|
||||||
return *this; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
No, this is not an evil backdoor. QT_BUILD_INTERNAL just exports more symbols
|
No, this is not an evil backdoor. QT_BUILD_INTERNAL just exports more symbols
|
||||||
for Qt's internal unit tests. If you want slower loading times and more
|
for Qt's internal unit tests. If you want slower loading times and more
|
||||||
@ -244,26 +186,6 @@ typedef void (*QFunctionPointer)();
|
|||||||
# define Q_UNIMPLEMENTED() qWarning("Unimplemented code.")
|
# define Q_UNIMPLEMENTED() qWarning("Unimplemented code.")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
Compilers which follow outdated template instantiation rules
|
|
||||||
require a class to have a comparison operator to exist when
|
|
||||||
a QList of this type is instantiated. It's not actually
|
|
||||||
used in the list, though. Hence the dummy implementation.
|
|
||||||
Just in case other code relies on it we better trigger a warning
|
|
||||||
mandating a real implementation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef Q_FULL_TEMPLATE_INSTANTIATION
|
|
||||||
# define Q_DUMMY_COMPARISON_OPERATOR(C) \
|
|
||||||
bool operator==(const C&) const { \
|
|
||||||
qWarning(#C"::operator==(const "#C"&) was called"); \
|
|
||||||
return false; \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
|
|
||||||
# define Q_DUMMY_COMPARISON_OPERATOR(C)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QT_WARNING_PUSH
|
QT_WARNING_PUSH
|
||||||
// warning: noexcept-expression evaluates to 'false' because of a call to 'void swap(..., ...)'
|
// warning: noexcept-expression evaluates to 'false' because of a call to 'void swap(..., ...)'
|
||||||
QT_WARNING_DISABLE_GCC("-Wnoexcept")
|
QT_WARNING_DISABLE_GCC("-Wnoexcept")
|
||||||
@ -328,33 +250,8 @@ constexpr std::underlying_type_t<Enum> qToUnderlying(Enum e) noexcept
|
|||||||
return static_cast<std::underlying_type_t<Enum>>(e);
|
return static_cast<std::underlying_type_t<Enum>>(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> inline T *qGetPtrHelper(T *ptr) noexcept { return ptr; }
|
|
||||||
template <typename Ptr> inline auto qGetPtrHelper(Ptr &ptr) noexcept -> decltype(ptr.get())
|
|
||||||
{ static_assert(noexcept(ptr.get()), "Smart d pointers for Q_DECLARE_PRIVATE must have noexcept get()"); return ptr.get(); }
|
|
||||||
|
|
||||||
// The body must be a statement:
|
// The body must be a statement:
|
||||||
#define Q_CAST_IGNORE_ALIGN(body) QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wcast-align") body QT_WARNING_POP
|
#define Q_CAST_IGNORE_ALIGN(body) QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wcast-align") body QT_WARNING_POP
|
||||||
#define Q_DECLARE_PRIVATE(Class) \
|
|
||||||
inline Class##Private* d_func() noexcept \
|
|
||||||
{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr));) } \
|
|
||||||
inline const Class##Private* d_func() const noexcept \
|
|
||||||
{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr));) } \
|
|
||||||
friend class Class##Private;
|
|
||||||
|
|
||||||
#define Q_DECLARE_PRIVATE_D(Dptr, Class) \
|
|
||||||
inline Class##Private* d_func() noexcept \
|
|
||||||
{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(Dptr));) } \
|
|
||||||
inline const Class##Private* d_func() const noexcept \
|
|
||||||
{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(Dptr));) } \
|
|
||||||
friend class Class##Private;
|
|
||||||
|
|
||||||
#define Q_DECLARE_PUBLIC(Class) \
|
|
||||||
inline Class* q_func() noexcept { return static_cast<Class *>(q_ptr); } \
|
|
||||||
inline const Class* q_func() const noexcept { return static_cast<const Class *>(q_ptr); } \
|
|
||||||
friend class Class;
|
|
||||||
|
|
||||||
#define Q_D(Class) Class##Private * const d = d_func()
|
|
||||||
#define Q_Q(Class) Class * const q = q_func()
|
|
||||||
|
|
||||||
#define QT_MODULE(x)
|
#define QT_MODULE(x)
|
||||||
|
|
||||||
|
144
src/corelib/global/qtclasshelpermacros.h
Normal file
144
src/corelib/global/qtclasshelpermacros.h
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
// Copyright (C) 2022 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
#ifndef QTCLASSHELPERMACROS_H
|
||||||
|
#define QTCLASSHELPERMACROS_H
|
||||||
|
|
||||||
|
#include <QtCore/qtconfigmacros.h>
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#pragma qt_class(QtClassHelperMacros)
|
||||||
|
#pragma qt_sync_stop_processing
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Some classes do not permit copies to be made of an object. These
|
||||||
|
classes contains a private copy constructor and assignment
|
||||||
|
operator to disable copying (the compiler gives an error message).
|
||||||
|
*/
|
||||||
|
#define Q_DISABLE_COPY(Class) \
|
||||||
|
Class(const Class &) = delete;\
|
||||||
|
Class &operator=(const Class &) = delete;
|
||||||
|
|
||||||
|
#define Q_DISABLE_COPY_MOVE(Class) \
|
||||||
|
Q_DISABLE_COPY(Class) \
|
||||||
|
Class(Class &&) = delete; \
|
||||||
|
Class &operator=(Class &&) = delete;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Implementing a move assignment operator using an established
|
||||||
|
technique (move-and-swap, pure swap) is just boilerplate.
|
||||||
|
Here's a couple of *private* macros for convenience.
|
||||||
|
|
||||||
|
To know which one to use:
|
||||||
|
|
||||||
|
* if you don't have a move constructor (*) => use pure swap;
|
||||||
|
* if you have a move constructor, then
|
||||||
|
* if your class holds just memory (no file handles, no user-defined
|
||||||
|
datatypes, etc.) => use pure swap;
|
||||||
|
* use move and swap.
|
||||||
|
|
||||||
|
The preference should always go for the move-and-swap one, as it
|
||||||
|
will deterministically destroy the data previously held in *this,
|
||||||
|
and not "dump" it in the moved-from object (which may then be alive
|
||||||
|
for longer).
|
||||||
|
|
||||||
|
The requirement for either macro is the presence of a member swap(),
|
||||||
|
which any value class that defines its own special member functions
|
||||||
|
should have anyhow.
|
||||||
|
|
||||||
|
(*) Many value classes in Qt do not have move constructors; mostly,
|
||||||
|
the implicitly shared classes using QSharedDataPointer and friends.
|
||||||
|
The reason is mostly historical: those classes require either an
|
||||||
|
out-of-line move constructor, which we could not provide before we
|
||||||
|
made C++11 mandatory (and that we don't like anyhow), or
|
||||||
|
an out-of-line dtor for the Q(E)DSP<Private> member (cf. QPixmap).
|
||||||
|
|
||||||
|
If you can however add a move constructor to a class lacking it,
|
||||||
|
consider doing so, then reevaluate which macro to choose.
|
||||||
|
*/
|
||||||
|
#define QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(Class) \
|
||||||
|
Class &operator=(Class &&other) noexcept { \
|
||||||
|
Class moved(std::move(other)); \
|
||||||
|
swap(moved); \
|
||||||
|
return *this; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Class) \
|
||||||
|
Class &operator=(Class &&other) noexcept { \
|
||||||
|
swap(other); \
|
||||||
|
return *this; \
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> inline T *qGetPtrHelper(T *ptr) noexcept { return ptr; }
|
||||||
|
template <typename Ptr> inline auto qGetPtrHelper(Ptr &ptr) noexcept -> decltype(ptr.get())
|
||||||
|
{ static_assert(noexcept(ptr.get()), "Smart d pointers for Q_DECLARE_PRIVATE must have noexcept get()"); return ptr.get(); }
|
||||||
|
|
||||||
|
#define Q_DECLARE_PRIVATE(Class) \
|
||||||
|
inline Class##Private* d_func() noexcept \
|
||||||
|
{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr));) } \
|
||||||
|
inline const Class##Private* d_func() const noexcept \
|
||||||
|
{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr));) } \
|
||||||
|
friend class Class##Private;
|
||||||
|
|
||||||
|
#define Q_DECLARE_PRIVATE_D(Dptr, Class) \
|
||||||
|
inline Class##Private* d_func() noexcept \
|
||||||
|
{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(Dptr));) } \
|
||||||
|
inline const Class##Private* d_func() const noexcept \
|
||||||
|
{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(Dptr));) } \
|
||||||
|
friend class Class##Private;
|
||||||
|
|
||||||
|
#define Q_DECLARE_PUBLIC(Class) \
|
||||||
|
inline Class* q_func() noexcept { return static_cast<Class *>(q_ptr); } \
|
||||||
|
inline const Class* q_func() const noexcept { return static_cast<const Class *>(q_ptr); } \
|
||||||
|
friend class Class;
|
||||||
|
|
||||||
|
#define Q_D(Class) Class##Private * const d = d_func()
|
||||||
|
#define Q_Q(Class) Class * const q = q_func()
|
||||||
|
|
||||||
|
/*
|
||||||
|
Compilers which follow outdated template instantiation rules
|
||||||
|
require a class to have a comparison operator to exist when
|
||||||
|
a QList of this type is instantiated. It's not actually
|
||||||
|
used in the list, though. Hence the dummy implementation.
|
||||||
|
Just in case other code relies on it we better trigger a warning
|
||||||
|
mandating a real implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef Q_FULL_TEMPLATE_INSTANTIATION
|
||||||
|
# define Q_DUMMY_COMPARISON_OPERATOR(C) \
|
||||||
|
bool operator==(const C&) const { \
|
||||||
|
qWarning(#C"::operator==(const "#C"&) was called"); \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
# define Q_DUMMY_COMPARISON_OPERATOR(C)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
Specialize a shared type with:
|
||||||
|
|
||||||
|
Q_DECLARE_SHARED(type)
|
||||||
|
|
||||||
|
where 'type' is the name of the type to specialize. NOTE: shared
|
||||||
|
types must define a member-swap, and be defined in the same
|
||||||
|
namespace as Qt for this to work.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define Q_DECLARE_SHARED_IMPL(TYPE, FLAGS) \
|
||||||
|
Q_DECLARE_TYPEINFO(TYPE, FLAGS); \
|
||||||
|
inline void swap(TYPE &value1, TYPE &value2) \
|
||||||
|
noexcept(noexcept(value1.swap(value2))) \
|
||||||
|
{ value1.swap(value2); }
|
||||||
|
#define Q_DECLARE_SHARED(TYPE) Q_DECLARE_SHARED_IMPL(TYPE, Q_RELOCATABLE_TYPE)
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // QTCLASSHELPERMACROS_H
|
59
src/corelib/global/qtclasshelpermacros.qdoc
Normal file
59
src/corelib/global/qtclasshelpermacros.qdoc
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// Copyright (C) 2022 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\macro Q_DISABLE_COPY(Class)
|
||||||
|
\relates QtClassHelperMacros
|
||||||
|
|
||||||
|
Disables the use of copy constructors and assignment operators
|
||||||
|
for the given \a Class.
|
||||||
|
|
||||||
|
Instances of subclasses of QObject should not be thought of as
|
||||||
|
values that can be copied or assigned, but as unique identities.
|
||||||
|
This means that when you create your own subclass of QObject
|
||||||
|
(director or indirect), you should \e not give it a copy constructor
|
||||||
|
or an assignment operator. However, it may not enough to simply
|
||||||
|
omit them from your class, because, if you mistakenly write some code
|
||||||
|
that requires a copy constructor or an assignment operator (it's easy
|
||||||
|
to do), your compiler will thoughtfully create it for you. You must
|
||||||
|
do more.
|
||||||
|
|
||||||
|
The curious user will have seen that the Qt classes derived
|
||||||
|
from QObject typically include this macro in a private section:
|
||||||
|
|
||||||
|
\snippet code/src_corelib_global_qglobal.cpp 43
|
||||||
|
|
||||||
|
It declares a copy constructor and an assignment operator in the
|
||||||
|
private section, so that if you use them by mistake, the compiler
|
||||||
|
will report an error.
|
||||||
|
|
||||||
|
\snippet code/src_corelib_global_qglobal.cpp 44
|
||||||
|
|
||||||
|
But even this might not catch absolutely every case. You might be
|
||||||
|
tempted to do something like this:
|
||||||
|
|
||||||
|
\snippet code/src_corelib_global_qglobal.cpp 45
|
||||||
|
|
||||||
|
First of all, don't do that. Most compilers will generate code that
|
||||||
|
uses the copy constructor, so the privacy violation error will be
|
||||||
|
reported, but your C++ compiler is not required to generate code for
|
||||||
|
this statement in a specific way. It could generate code using
|
||||||
|
\e{neither} the copy constructor \e{nor} the assignment operator we
|
||||||
|
made private. In that case, no error would be reported, but your
|
||||||
|
application would probably crash when you called a member function
|
||||||
|
of \c{w}.
|
||||||
|
|
||||||
|
\sa Q_DISABLE_COPY_MOVE
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\macro Q_DISABLE_COPY_MOVE(Class)
|
||||||
|
\relates QtClassHelperMacros
|
||||||
|
|
||||||
|
A convenience macro that disables the use of copy constructors, assignment
|
||||||
|
operators, move constructors and move assignment operators for the given
|
||||||
|
\a Class.
|
||||||
|
|
||||||
|
\sa Q_DISABLE_COPY
|
||||||
|
\since 5.13
|
||||||
|
*/
|
@ -143,23 +143,6 @@ template<typename T> class QFlags;
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
Q_DECLARE_TYPEINFO_BODY(QFlags<T>, Q_PRIMITIVE_TYPE);
|
Q_DECLARE_TYPEINFO_BODY(QFlags<T>, Q_PRIMITIVE_TYPE);
|
||||||
|
|
||||||
/*
|
|
||||||
Specialize a shared type with:
|
|
||||||
|
|
||||||
Q_DECLARE_SHARED(type)
|
|
||||||
|
|
||||||
where 'type' is the name of the type to specialize. NOTE: shared
|
|
||||||
types must define a member-swap, and be defined in the same
|
|
||||||
namespace as Qt for this to work.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define Q_DECLARE_SHARED_IMPL(TYPE, FLAGS) \
|
|
||||||
Q_DECLARE_TYPEINFO(TYPE, FLAGS); \
|
|
||||||
inline void swap(TYPE &value1, TYPE &value2) \
|
|
||||||
noexcept(noexcept(value1.swap(value2))) \
|
|
||||||
{ value1.swap(value2); }
|
|
||||||
#define Q_DECLARE_SHARED(TYPE) Q_DECLARE_SHARED_IMPL(TYPE, Q_RELOCATABLE_TYPE)
|
|
||||||
|
|
||||||
namespace QTypeTraits
|
namespace QTypeTraits
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user