Long live Q_DECLARE_SHARED_NS!
We used to mark Q_DECLARE_SHARED all our value classes in Qt 4 times, but since many Qt types these days live in nested namespaces that macro, which only works in the QT_NAMESPACE, has become less useful. As we use it in more and more places and eventually add more responsibilities to it, we don't want every module to define its version by hand, like QT3D_DECLARE_SHARED did in 2016 already. So add two namespace-aware versions of Q_DECLARE_SHARED, to be used inside or outside nested namespaces. Extend the test. Despite the name, this is not a public macro. Found missing Q_D_S in API-review, so picking this to 6.8 to aid with fixing the 6.8 API. Change-Id: I367ca0d5b005b64090de44f7b7541d8639f9a4e0 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> (cherry picked from commit 37b2b2ea4ef3cf494d23885de186a9519763e744) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
dc3b7d2203
commit
19fbb338b8
@ -141,10 +141,55 @@ namespace QtPrivate {
|
||||
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.
|
||||
|
||||
For types defined in a namespace within QT_NAMESPACE, use
|
||||
Q_DECLARE_SHARED_NS/_EXT instead. The _NS macro needs to be placed
|
||||
inside the nested namespace:
|
||||
|
||||
namespace ns {
|
||||
// ~~~ type defined here ~~~
|
||||
Q_DECLARE_SHARED_NS(ns, type)
|
||||
}
|
||||
|
||||
while the _NS_EXT macro goes into the QT_NAMESPACE, outside any
|
||||
nested namespaces:
|
||||
|
||||
namespace ns {
|
||||
// ~~~ type defined here ~~~
|
||||
}
|
||||
Q_DECLARE_SHARED_NS_EXT(ns, type)
|
||||
|
||||
The latter then also works for more deeply-nested namespaces:
|
||||
|
||||
Q_DECLARE_SHARED_NS_EXT(ns1::ns2, type)
|
||||
|
||||
Q_DECLARE_SHARED_NS does, too, if all namespaces were opened in one statement:
|
||||
|
||||
namespace ns1::ns2 {
|
||||
Q_DECLARE_SHARED_NS(ns1::ns2, type);
|
||||
}
|
||||
*/
|
||||
|
||||
#define Q_DECLARE_SHARED(TYPE) \
|
||||
QT_DECLARE_ADL_SWAP(TYPE) \
|
||||
Q_DECLARE_TYPEINFO(TYPE, Q_RELOCATABLE_TYPE); \
|
||||
/* end */
|
||||
|
||||
#define Q_DECLARE_SHARED_NS(NS, TYPE) \
|
||||
QT_DECLARE_ADL_SWAP(TYPE) \
|
||||
} /* namespace NS */ \
|
||||
Q_DECLARE_TYPEINFO(NS :: TYPE, Q_RELOCATABLE_TYPE); \
|
||||
namespace NS { \
|
||||
/* end */
|
||||
|
||||
#define Q_DECLARE_SHARED_NS_EXT(NS, TYPE) \
|
||||
namespace NS { \
|
||||
QT_DECLARE_ADL_SWAP(TYPE) \
|
||||
} /* namespace NS */ \
|
||||
Q_DECLARE_TYPEINFO(NS :: TYPE, Q_RELOCATABLE_TYPE); \
|
||||
/* end */
|
||||
|
||||
#define QT_DECLARE_ADL_SWAP(TYPE) \
|
||||
inline void swap(TYPE &value1, TYPE &value2) \
|
||||
noexcept(noexcept(value1.swap(value2))) \
|
||||
{ value1.swap(value2); }
|
||||
|
@ -42,6 +42,27 @@ static_assert(!q_is_adl_swappable_v<NotQDeclareShared>);
|
||||
MAKE_CLASS(Terry); // R.I.P.
|
||||
Q_DECLARE_SHARED(Terry)
|
||||
|
||||
namespace Discworld {
|
||||
MAKE_CLASS(Librarian);
|
||||
Q_DECLARE_SHARED_NS(Discworld, Librarian)
|
||||
MAKE_CLASS(Baggage);
|
||||
namespace AnkhMorpork {
|
||||
MAKE_CLASS(Vetinari);
|
||||
// Q_DECLARE_SHARED_NS only work on a single nesting level
|
||||
namespace CityWatch {
|
||||
MAKE_CLASS(Vimes);
|
||||
} // namespace CityWatch
|
||||
} // namespace AnkhMorpork
|
||||
} // namespace Discworld
|
||||
Q_DECLARE_SHARED_NS_EXT(Discworld, Baggage)
|
||||
Q_DECLARE_SHARED_NS_EXT(Discworld::AnkhMorpork, Vetinari)
|
||||
Q_DECLARE_SHARED_NS_EXT(Discworld::AnkhMorpork::CityWatch, Vimes)
|
||||
// but Q_DECLARE_SHARED_NS works if all namespaces are opened in one statement:
|
||||
namespace Discworld::AnkhMorpork {
|
||||
MAKE_CLASS(Leonardo);
|
||||
Q_DECLARE_SHARED_NS(Discworld::AnkhMorpork, Leonardo)
|
||||
} // namespace Discworld::AnkhMorpork
|
||||
|
||||
#undef MAKE_CLASS
|
||||
|
||||
QT_END_NAMESPACE
|
||||
@ -432,12 +453,22 @@ void tst_QGlobal::qDeclareSharedMarksTheTypeRelocatable()
|
||||
{
|
||||
static_assert(!QTypeInfo<QT_PREPEND_NAMESPACE(NotQDeclareShared)>::isRelocatable);
|
||||
static_assert( QTypeInfo<QT_PREPEND_NAMESPACE(Terry)>::isRelocatable);
|
||||
static_assert( QTypeInfo<QT_PREPEND_NAMESPACE(Discworld::Librarian)>::isRelocatable);
|
||||
static_assert( QTypeInfo<QT_PREPEND_NAMESPACE(Discworld::Baggage)>::isRelocatable);
|
||||
static_assert( QTypeInfo<QT_PREPEND_NAMESPACE(Discworld::AnkhMorpork::Vetinari)>::isRelocatable);
|
||||
static_assert( QTypeInfo<QT_PREPEND_NAMESPACE(Discworld::AnkhMorpork::Leonardo)>::isRelocatable);
|
||||
static_assert( QTypeInfo<QT_PREPEND_NAMESPACE(Discworld::AnkhMorpork::CityWatch::Vimes)>::isRelocatable);
|
||||
}
|
||||
|
||||
void tst_QGlobal::qDeclareSharedMakesTheTypeAdlSwappable()
|
||||
{
|
||||
static_assert(!q_is_adl_swappable_v<QT_PREPEND_NAMESPACE(NotQDeclareShared)>);
|
||||
static_assert( q_is_adl_swappable_v<QT_PREPEND_NAMESPACE(Terry)>);
|
||||
static_assert( q_is_adl_swappable_v<QT_PREPEND_NAMESPACE(Discworld::Librarian)>);
|
||||
static_assert( q_is_adl_swappable_v<QT_PREPEND_NAMESPACE(Discworld::Baggage)>);
|
||||
static_assert( q_is_adl_swappable_v<QT_PREPEND_NAMESPACE(Discworld::AnkhMorpork::Vetinari)>);
|
||||
static_assert( q_is_adl_swappable_v<QT_PREPEND_NAMESPACE(Discworld::AnkhMorpork::Leonardo)>);
|
||||
static_assert( q_is_adl_swappable_v<QT_PREPEND_NAMESPACE(Discworld::AnkhMorpork::CityWatch::Vimes)>);
|
||||
|
||||
#define CHECK(Class) do { \
|
||||
using C = QT_PREPEND_NAMESPACE(Class); \
|
||||
@ -451,6 +482,11 @@ void tst_QGlobal::qDeclareSharedMakesTheTypeAdlSwappable()
|
||||
QCOMPARE_EQ(rhs.s, "lhs"); \
|
||||
} while (false)
|
||||
CHECK(Terry);
|
||||
CHECK(Discworld::Librarian);
|
||||
CHECK(Discworld::Baggage);
|
||||
CHECK(Discworld::AnkhMorpork::Vetinari);
|
||||
CHECK(Discworld::AnkhMorpork::Leonardo);
|
||||
CHECK(Discworld::AnkhMorpork::CityWatch::Vimes);
|
||||
#undef CHECK
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user