5

QVariant::isNull()カスタムQ_DECLARE_METATYPE()タイプでどうにか使えますか?

たとえば、整数に対してそのようなラッパー クラスを定義するとします (なぜそうする必要があるのですが、これは最小限の例である必要があります)。メンバー関数を定義bool isNull() constしても役に立ちません:

#include <QVariant>
#include <QDebug>

class Integer {
    bool null;
    int x;
public:
    Integer() : null(true), x(0) {}
    Integer(int x) : null(false), x(x) {}
    int value() const {
        return x;
    }
    bool isNull() const {
        return null;
    }
};
Q_DECLARE_METATYPE(Integer)

int main()
{
    Integer x(42);
    Integer y(0);
    Integer z;

    qDebug() << x.isNull() << QVariant::fromValue(x).isNull();
    qDebug() << y.isNull() << QVariant::fromValue(y).isNull();
    qDebug() << z.isNull() << QVariant::fromValue(z).isNull(); // Not as expected!
}

出力:

false false 
false false 
true false     // Not as expected!
4

1 に答える 1

7

残念ながらできません。QVariant::isNullコードは次のとおりです。

static bool isNull(const QVariant::Private *d)
{
    switch(d->type) {
    case QVariant::String:
        return v_cast<QString>(d)->isNull();
    case QVariant::Char:
        return v_cast<QChar>(d)->isNull();
    case QVariant::Date:
        return v_cast<QDate>(d)->isNull();
    case QVariant::Time:
        return v_cast<QTime>(d)->isNull();
    ...
    }
    return d->is_null;
}

ご覧のとおりisNull()、いくつかの一般的な変数タイプの関数を明示的に使用し、デフォルトでd->is_null値を返します。

は、初期化されるクラスd->is_nullの D ポインターのクラス メンバーですが、値を代入するたびに次のようになります。QVarianttrueQVariantfalse

inline void qVariantSetValue(QVariant &v, const T &t)
{
    ...
    d.is_null = false;
    ...
}

したがって、カスタム タイプの場合は常に が返されfalseます。

1 つの可能性 (これはお勧めしません) は、関数をサブクラス化QVariantして再実装するisNullことです。この関数では、型がカスタムかどうかを確認できます。この場合isNull、カスタム クラスの関数の戻り値を返すことができます。それ以外の場合は、QVariant::isNull関数の戻り値を返す必要があります。

bool MyQVariant::isNull() const
{
    if (QString(typeName()) == "MyCustomClass")
       return value<MyCustomClass>().isNull();
    return QVariant::isNull();   
}

編集

サブクラス化された QVariant を使用したコード例:

#include <QVariant>
#include <QDebug>

class Integer {
    bool null;
    int x;
public:
    Integer() : null(true), x(0) {}
    Integer(int x) : null(false), x(x) {}
    int value() const {
        return x;
    }
    bool isNull() const {
        return null;
    }
};
Q_DECLARE_METATYPE(Integer)

class MyQVariant : public QVariant
{
public:
    MyQVariant(QVariant v) :
      QVariant(v) {}
    bool isNull() const
    {
        if (QString(typeName()) == "Integer")
            return value<Integer>().isNull();
        return QVariant::isNull();   
    }
};

int main(int argc, char *argv[])
{
    Integer x(42);
    Integer y(0);
    Integer z;

    qRegisterMetaType<Integer>("Integer");

    MyQVariant v1(QVariant::fromValue(x));
    MyQVariant v2(QVariant::fromValue(y));
    MyQVariant v3(QVariant::fromValue(z));

    qDebug() << x.isNull() << v1.isNull();
    qDebug() << y.isNull() << v2.isNull();
    qDebug() << z.isNull() << v3.isNull();
}

出力:

false false 
false false 
true true
于 2013-01-24T10:58:57.337 に答える