1. Q_DECLARE_METATYPE 的定义:
【为了方便阅读, 内容有删节。】
功能: 声明了 模板函数 QMetaTypeId< TYPE >::qt_metatype_id ,虽然内部 调用了 qRegisterMetaType, 但是 只有执行qt_metatype_id, 才会使 qRegisterMetaType 生效。
执行的方式就是: QVariant::fromValue<T>()
Note:
#define Q_DECLARE_METATYPE(TYPE) Q_DECLARE_METATYPE_IMPL(TYPE)
#define Q_DECLARE_METATYPE_IMPL(TYPE) \
QT_BEGIN_NAMESPACE \
template <> \
struct QMetaTypeId< TYPE > \
{ \
enum { Defined = 1 }; \
static int qt_metatype_id() \
{ \
static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
if (const int id = metatype_id.loadAcquire()) \
return id; \
const int newId = qRegisterMetaType< TYPE >(#TYPE, \
reinterpret_cast< TYPE *>(quintptr(-1))); \
metatype_id.storeRelease(newId); \
return newId; \
} \
}; \
QT_END_NAMESPACE
2. qRegisterMetaType 实现
建立 StringLiteral 到 类型构造 析构的路径。 以实现 connect 的 功能
QObject::connect 内部是通过 “函数签名” 解析来 实现的。所以使用 qRegisterMetaType 就可以保证 queued类型的connection 能正确执行。
template <typename T>
int qRegisterMetaType(const char *typeName)
{
QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName =
QMetaObject::normalizedType(typeName);
return qRegisterNormalizedMetaType<T>(normalizedTypeName, dummy, defined);
}
qRegisterNormalizedMetaType
template <typename T>
int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName
)
{
const int id = QMetaType::registerNormalizedType(normalizedTypeName,
QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Destruct,
QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Construct,
int(sizeof(T)),
flags,
QtPrivate::MetaObjectForType<T>::value());
if (id > 0) {
QtPrivate::SequentialContainerConverterHelper<T>::registerConverter(id);
QtPrivate::AssociativeContainerConverterHelper<T>::registerConverter(id);
QtPrivate::MetaTypePairHelper<T>::registerConverter(id);
QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter(id);
}
return id;
}
建立内存的对象创建 和 析构过程
namespace QtMetaTypePrivate {
template <typename T, bool Accepted = true>
struct QMetaTypeFunctionHelper {
static void Destruct(void *t)
{
Q_UNUSED(t) // Silence MSVC that warns for POD types.
static_cast<T*>(t)->~T();
}
static void *Construct(void *where, const void *t)
{
if (t)
return new (where) T(*static_cast<const T*>(t));
return new (where) T;
}
#ifndef QT_NO_DATASTREAM
static void Save(QDataStream &stream, const void *t)
{
stream << *static_cast<const T*>(t);
}
static void Load(QDataStream &stream, void *t)
{
stream >> *static_cast<T*>(t);
}
#endif // QT_NO_DATASTREAM
};
3. QVariant 对 MetaType 的 使用:
3.1 直接从内部支持类 构建 以 QRectF 为例
QVariant::QVariant(const QRectF &r)
: d(RectF)
{ v_construct<QRectF>(&d, r); }
template <class T>
inline void v_construct(QVariant::Private *x, const T &t)
{
// dispatch
v_construct_helper(x, t, typename QVariantIntegrator<T>::CanUseInternalSpace_t());
}
QVariantIntegrator 对类型 的 size 是否 < Private::Data 的大小
template<typename T>
struct QVariantIntegrator
{
static const bool CanUseInternalSpace = sizeof(T) <= sizeof(QVariant::Private::Data)
&& ((QTypeInfoQuery<T>::isRelocatable) || std::is_enum<T>::value);
typedef std::integral_constant<bool, CanUseInternalSpace> CanUseInternalSpace_t;
};
类型 的 size 是否 > Private::Data 的大小 , 重新分配内存 以指针方式存储。
template <class T>
inline void v_construct_helper(QVariant::Private *x, const T &t, std::false_type)
{
x->data.shared = new QVariantPrivateSharedEx<T>(t);
x->is_shared = true;
}
类型 的 size 是否 <= Private::Data 的大小 , 构造创建。
template <class T>
inline void v_construct_helper(QVariant::Private *x, const T &t, std::true_type)
{
new (&x->data) T(t);
x->is_shared = false;
}
3.2 从 非内部支持类 构建
template<typename T>
inline T value() const
{ return qvariant_cast<T>(*this); }
template<typename T>
static inline QVariant fromValue(const T &value)
{ return qVariantFromValue(value); }
template <typename T>
inline QVariant qVariantFromValue(const T &t)
{
return QVariant(qMetaTypeId<T>(), &t, QTypeInfo<T>::isPointer);
}
按照 是否指针类型 区别对待 ( 非指针进行 create )
QVariant::QVariant(int typeId, const void *copy, uint flags)
{
if (flags) { //type is a pointer type
d.type = typeId;
d.data.ptr = *reinterpret_cast<void *const*>(copy);
} else {
create(typeId, copy);
}
d.is_null = false;
}
void QVariant::create(int type, const void *copy)
{
d.type = type;
handlerManager[type]->construct(&d, copy);
}
template <class T>
inline void v_construct_helper(QVariant::Private *x, const T &t, std::false_type)
{
x->data.shared = new QVariantPrivateSharedEx<T>(t);
x->is_shared = true;
}
template <class T>
inline void v_construct_helper(QVariant::Private *x, std::true_type)
{
new (&x->data) T();
x->is_shared = false;
}