本文介绍了QVariant中的自定义类型转换为空字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个词法扫描器,它从某些输入生成令牌流.这些令牌具有 type value .由于我使用的是Qt,因此我选择将令牌数据存储为QVariant.对于非自定义类型的令牌数据,此方法效果很好.

I'm writing a lexical scanner that generates a stream of tokens from some input. Those tokens have a type and a value. Since I'm using Qt I chose to store the token data as a QVariant. This works pretty well for token data that is of a non-custom type.

不幸的是,我还有几种自定义类型,它们也存储在令牌中.令牌具有toString()函数,该函数输出令牌描述(用于调试),但是对于所有具有自定义类型数据的令牌,此函数将提供一个空字符串.代码如下:

Unfortunately, I have several custom types that are stored inside of tokens as well. The tokens have a toString() function that outputs a token description (for debugging), but for all tokens that have data of a custom type this function gives an empty string. The code goes like this:

Test.h:

struct Test
{
    QString value_;

    Test(const QString& value = "");
    QString toString();
};

Q_DECLARE_METATYPE(Test)

Token.h:

struct Token
{
    TokenType type_;
    QVariant value_;
...
    virtual QString toString() const;
};

Token.cpp:

Token.cpp:

QString Token::toString() const
{
    QStringList sl;
    sl << "Token(" << ::toString(type_) << ", ";
    sl << value_.toString() << ")";
    return sl.join("");
}

扫描仪输出示例:

"Token(TT_TEST, )"
"Token(TT_PLUS, +)"
"Token(TT_NUMBER, 5)"
"Token(TT_end, #)"

TT_TEST令牌包含一个Test类,我希望该变体能够打印出它的值.不幸的是,这不起作用,并且我尝试了许多无效的解决方案.我当前的解决方法如下:

The TT_TEST token contains a Test class and I would expect the variant to print it's value. Unfortunately this does not work, and I've tried a lot of solutions that did not work. My current workaround looks like this:

template <typename T>
bool writeToStringList(QStringList& sl, QVariant v)
{
    if (!v.canConvert<T>()) return false;
    sl << v.value<T>().toString();
    return true;
}

和修改后的toString()函数:

sl << "Token(";
sl << ::toString(type_) << ", ";
if (!writeToStringList<Test>(sl, value_)) {
    sl << value_.toString();
}

我必须对所有自定义类型都这样做,这感觉非常笨拙和错误.

and I have to do this for all my custom types which just feels pretty clumsy and wrong.

我认为必须对此问题有更好的解决方案.你们任何人都可以:

I figure there must be a better solution to this problem. Can anyone of you:

  • 告诉我如何更好地解决QVariant问题,或者
  • 建议不使用QVariant的完全不同的解决方案. (我之前有一个模板解决方案,但在那里遇到了不同的问题,因此,如果有建议,我将需要一个示例.)
  • Tell me how to solve the problem with the QVariant in a better way, or
  • suggest a totally different solution without a QVariant. (I had a template solution earlier but I ran into different problems there, so I would need an example if that is suggested).

?

推荐答案

Q_DECLARE_METATYPE()实际上足以在QVariant中启用自定义类型的聚合.但是,这并不涵盖诸如隐式类型转换和QVariant上下文中的比较之类的方面.假设使用Qt5,以便于隐式转换为QString,您可以执行以下操作:

Q_DECLARE_METATYPE() is in fact sufficient to enable aggregation of a custom type in a QVariant. This does not cover aspects like implicit type conversion and comparison in context of the QVariant though.Qt5 assumed, to facilitate implicit conversion to QString you may do the following:

#include <QMetaType>

struct Token {
    QString _value;
};

Q_DECLARE_METATYPE( Token* );

QString tokenToString( Token* t ) {
   return t->_value );
}

int main(int argc, char* argv[]) {
    QMetaType::registerConverter<Token*,QString>( tokenToString );

    Token t = { QString("hello") };
    QVariant value;
    value.setValue( &t );
    std::cout << value << std::endl;
}

使用Q_DECLARE_METATYPE( MyType )当然也可以(并且更节省),并且可以直接在QVariant中聚集Token实例,而不是指向Token的指针.

This is of course also possible (and more save) with Q_DECLARE_METATYPE( MyType ) and directly aggregating a Token instance in the QVariant instead of a pointer to Token.

另请参见来自Qt论坛的帖子

这篇关于QVariant中的自定义类型转换为空字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 02:57
查看更多