Qt AbstractConverterFunction ConverterMemberFunction

Qt中,QT_FOR_EACH_STATIC_TYPE是一个很关键的宏,在很多地方都有用到,QT_FOR_EACH_STATIC_TYPE(Q_DECLARE_BUILTIN_METATYPE) 将qt中的类型

下面的代码将QT_FOR_EACH_STATIC_TYPE、QT_FOR_EACH_STATIC_HACKS_TYPE、QT_FOR_EACH_STATIC_ALIAS_TYPE中标注的类型信息初始化到types这个全局静态数组变量中

//QtInstallDir\Src\qtbase\src\corelib\kernel\qmetatype.cpp
.......
#define QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, RealName) \
    { #RealName, sizeof(#RealName) - 1, MetaTypeId },

#define QT_ADD_STATIC_METATYPE_ALIASES_ITER(MetaTypeName, MetaTypeId, AliasingName, RealNameStr) \
    { RealNameStr, sizeof(RealNameStr) - 1, QMetaType::MetaTypeName },

#define QT_ADD_STATIC_METATYPE_HACKS_ITER(MetaTypeName, TypeId, Name) \
    QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeName, Name)

static const struct { const char * typeName; int typeNameLength; int type; } types[] = {
    QT_FOR_EACH_STATIC_TYPE(QT_ADD_STATIC_METATYPE)
    QT_FOR_EACH_STATIC_ALIAS_TYPE(QT_ADD_STATIC_METATYPE_ALIASES_ITER)
    QT_FOR_EACH_STATIC_HACKS_TYPE(QT_ADD_STATIC_METATYPE_HACKS_ITER)
    {0, 0, QMetaType::UnknownType}
};
.......

下面代码将QT_FOR_EACH_STATIC_TYPE中标注的类型信息初始化到metaTypeNames对象中metaTypeNames与上面的types变量功能是有重合的。但是types中记录有重复,比如ulong 与unsigned long是重复的,在metaTypeNames中只有ulong项。

namespace {
// All type names in one long string.
constexpr char metaTypeStrings[] = QT_FOR_EACH_STATIC_TYPE(STRINGIFY_TYPE_NAME);

// The sizes of the strings in the metaTypeStrings string (including terminating null)
constexpr short metaTypeNameSizes[] = {
    QT_FOR_EACH_STATIC_TYPE(CALCULATE_TYPE_LEN)
};

// The type IDs, in the order of the metaTypeStrings data
constexpr short metaTypeIds[] = {
    QT_FOR_EACH_STATIC_TYPE(MAP_TYPE_ID_TO_IDX)
};

constexpr int MetaTypeNameCount = sizeof(metaTypeNameSizes) / sizeof(metaTypeNameSizes[0]);

template <typename IntegerSequence> struct MetaTypeOffsets;
template <int... TypeIds> struct MetaTypeOffsets<QtPrivate::IndexesList<TypeIds...>>
{
    // This would have been a lot easier if the meta types that the macro
    // QT_FOR_EACH_STATIC_TYPE declared were in sorted, ascending order, but
    // they're not (i.e., the first one declared is QMetaType::Void == 43,
    // followed by QMetaType::Bool == 1)... As a consequence, we need to use
    // the C++11 constexpr function calculateOffsetForTypeId below in order to
    // create the offset array.

    static constexpr int findTypeId(int typeId, int i = 0)
    {
        return i >= MetaTypeNameCount ? -1 :
                metaTypeIds[i] == typeId ? i : findTypeId(typeId, i + 1);
    }

    static constexpr short calculateOffsetForIdx(int i)
    {
        return i < 0 ? -1 :
               i == 0 ? 0 : metaTypeNameSizes[i - 1] + calculateOffsetForIdx(i - 1);
    }

    static constexpr short calculateOffsetForTypeId(int typeId)
    {
        return calculateOffsetForIdx(findTypeId(typeId));
#if 0
        // same as, but this is only valid in C++14:
        short offset = 0;
        for (int i = 0; i < MetaTypeNameCount; ++i) {
            if (metaTypeIds[i] == typeId)
                return offset;
            offset += metaTypeNameSizes[i];
        }
        return -1;
#endif
    }

    short offsets[sizeof...(TypeIds)];
    constexpr MetaTypeOffsets() : offsets{calculateOffsetForTypeId(TypeIds)...} {}

    const char *operator[](int typeId) const Q_DECL_NOTHROW
    {
        short o = offsets[typeId];
        return o < 0 ? nullptr : metaTypeStrings + o;
    }
};
} // anonymous namespace

constexpr MetaTypeOffsets<QtPrivate::Indexes<QMetaType::HighestInternalId + 1>::Value> metaTypeNames {};

在qmetatype.h中,qt提供Q_DECLARE_METATYPE(TYPE) 宏来为用户自定义的类型进行注册。

//QtInstallDir\Src\qtbase\src\corelib\kernel\global.h
......
# define Q_DECL_EQ_DELETE = delete
#define Q_DISABLE_COPY(Class) \
    Class(const Class &) Q_DECL_EQ_DELETE;\
    Class &operator=(const Class &) Q_DECL_EQ_DELETE;
......
------------------------------------

//QtInstallDir\Src\qtbase\src\corelib\kernel\qmetatype.h
......
#define QT_FOR_EACH_STATIC_TYPE(F)\
    QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
    QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\
    QT_FOR_EACH_STATIC_CORE_CLASS(F)\
    QT_FOR_EACH_STATIC_CORE_POINTER(F)\
    QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)\
    QT_FOR_EACH_STATIC_GUI_CLASS(F)\
    QT_FOR_EACH_STATIC_WIDGETS_CLASS(F)\
.......

struct AbstractConverterFunction
{
    typedef bool (*Converter)(const AbstractConverterFunction *, const void *, void*);
    explicit AbstractConverterFunction(Converter c = nullptr)
        : convert(c) {}
    Q_DISABLE_COPY(AbstractConverterFunction)
    Converter convert;
};

template<typename From, typename To>
struct ConverterMemberFunction : public AbstractConverterFunction
{
    explicit ConverterMemberFunction(To(From::*function)() const)
        : AbstractConverterFunction(convert),
          m_function(function) {}
    ~ConverterMemberFunction();
    static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
    {
        const From *f = static_cast<const From *>(in);
        To *t = static_cast<To *>(out);
        const ConverterMemberFunction *_typedThis =
            static_cast<const ConverterMemberFunction *>(_this);
        *t = (f->*_typedThis->m_function)();
        return true;
    }

    To(From::* const m_function)() const;
};

template<typename From, typename To>
struct ConverterMemberFunctionOk : public AbstractConverterFunction
{
    explicit ConverterMemberFunctionOk(To(From::*function)(bool *) const)
        : AbstractConverterFunction(convert),
          m_function(function) {}
    ~ConverterMemberFunctionOk();
    static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
    {
        const From *f = static_cast<const From *>(in);
        To *t = static_cast<To *>(out);
        bool ok = false;
        const ConverterMemberFunctionOk *_typedThis =
            static_cast<const ConverterMemberFunctionOk *>(_this);
        *t = (f->*_typedThis->m_function)(&ok);
        if (!ok)
            *t = To();
        return ok;
    }

    To(From::* const m_function)(bool*) const;
};

template<typename From, typename To, typename UnaryFunction>
struct ConverterFunctor : public AbstractConverterFunction
{
    explicit ConverterFunctor(UnaryFunction function)
        : AbstractConverterFunction(convert),
          m_function(function) {}
    ~ConverterFunctor();
    static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
    {
        const From *f = static_cast<const From *>(in);
        To *t = static_cast<To *>(out);
        const ConverterFunctor *_typedThis =
            static_cast<const ConverterFunctor *>(_this);
        *t = _typedThis->m_function(*f);
        return true;
    }

    UnaryFunction m_function;
};
......

#define Q_DECLARE_BUILTIN_METATYPE(TYPE, METATYPEID, NAME) \
    QT_BEGIN_NAMESPACE \
    template<> struct QMetaTypeId2<NAME> \
    { \
        enum { Defined = 1, IsBuiltIn = true, MetaType = METATYPEID };   \
        static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return METATYPEID; } \
    }; \
    QT_END_NAMESPACE
...........

QT_FOR_EACH_STATIC_TYPE(Q_DECLARE_BUILTIN_METATYPE)



----------
//QtInstallDir\Src\qtbase\src\corelib\kernel\qmetatype.cpp
template<typename T, typename Key>
class QMetaTypeFunctionRegistry
{
public:
    ~QMetaTypeFunctionRegistry()
    {
        const QWriteLocker locker(&lock);
        map.clear();
    }

    bool contains(Key k) const
    {
        const QReadLocker locker(&lock);
        return map.contains(k);
    }

    bool insertIfNotContains(Key k, const T *f)
    {
        const QWriteLocker locker(&lock);
        const T* &fun = map[k];
        if (fun != 0)
            return false;
        fun = f;
        return true;
    }

    const T *function(Key k) const
    {
        const QReadLocker locker(&lock);
        return map.value(k, 0);
    }

    void remove(int from, int to)
    {
        const Key k(from, to);
        const QWriteLocker locker(&lock);
        map.remove(k);
    }
private:
    mutable QReadWriteLock lock;
    QHash<Key, const T *> map;
};

typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractConverterFunction,QPair<int,int> >
QMetaTypeConverterRegistry;
typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractComparatorFunction,int>
QMetaTypeComparatorRegistry;
typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int>
QMetaTypeDebugStreamRegistry;


bool QMetaType::registerConverterFunction(const QtPrivate::AbstractConverterFunction *f, int from, int to)
{
    if (!customTypesConversionRegistry()->insertIfNotContains(qMakePair(from, to), f)) {
        qWarning("Type conversion already registered from type %s to type %s",
                 QMetaType::typeName(from), QMetaType::typeName(to));
        return false;
    }
    return true;
}

/*!
    \internal

    Invoked automatically when a converter function object is destroyed.
 */
void QMetaType::unregisterConverterFunction(int from, int to)
{
    if (customTypesConversionRegistry.isDestroyed())
        return;
    customTypesConversionRegistry()->remove(from, to);
}


bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId)
{
    const QtPrivate::AbstractConverterFunction * const f =
        customTypesConversionRegistry()->function(qMakePair(fromTypeId, toTypeId));
    return f && f->convert(f, from, to);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值