Qt Q_DECLARE_METATYPE 和 qRegisterMetaType 的意义

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;
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值