[英]Custom type in QVariant converts to empty string
我正在编写一个词法扫描器,它从一些输入生成一个标记流。 这些令牌有一个type和一个value 。 由于我使用 Qt,我选择将令牌数据存储为QVariant
。 这对于非自定义类型的令牌数据非常有效。
不幸的是,我有几个自定义类型也存储在令牌中。 令牌有一个toString()
函数,该函数输出令牌描述(用于调试),但对于所有具有自定义类型数据的令牌,此函数给出一个空字符串。 代码是这样的:
测试.h:
struct Test
{
QString value_;
Test(const QString& value = "");
QString toString();
};
Q_DECLARE_METATYPE(Test)
令牌.h:
struct Token
{
TokenType type_;
QVariant value_;
...
virtual QString toString() const;
};
令牌.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 类,我希望该变体打印它的值。 不幸的是,这不起作用,我尝试了很多不起作用的解决方案。 我目前的解决方法是这样的:
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();
}
我必须为我所有的自定义类型都这样做,这感觉非常笨拙和错误。
我认为必须有更好的解决方案来解决这个问题。 你们中的任何人都可以:
QVariant
的问题,或者QVariant
的完全不同的解决方案。 (我之前有一个模板解决方案,但我在那里遇到了不同的问题,所以如果建议的话,我需要一个例子)。?
Q_DECLARE_METATYPE() 实际上足以在 QVariant 中启用自定义类型的聚合。 不过,这不包括隐式类型转换和 QVariant 上下文中的比较等方面。 假设 Qt5,为了便于隐式转换为 QString,您可以执行以下操作:
#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 的指针。
另请参阅Qt 论坛上的这篇文章
您需要为自定义类型 Token 注册一个 QString 转换器到元对象系统
为此,您有两种方法:
然后你可以直接将此方法注册为转换器
#include <QDebug>
#include <QMetaType>
#include <functional>
struct Token
{
QString toString() const
{
return _value;
}
QString _value;
};
Q_DECLARE_METATYPE( Token )
int main(int argc, char* argv[])
{
qRegisterMetaType<Token>();
QMetaType::registerConverter(&Token::toString);
Token t {"hello"};
QVariant value;
value.setValue( t );
qDebug() << value.toString();
}
然后你可以使用一元函数注册这个外部 toString 函数
#include <QDebug>
#include <QMetaType>
#include <functional>
struct Token
{
QString _value;
};
Q_DECLARE_METATYPE( Token )
QString tokenToString(const Token &t)
{
return t._value;
}
struct toQString : public std::unary_function<Token,QString>
{
QString operator() (const Token &value) const
{
return tokenToString(value);
}
};
int main(int argc, char* argv[])
{
qRegisterMetaType<Token>();
QMetaType::registerConverter<Token, QString, toQString>(toQString());
Token t {"hello"};
QVariant value;
value.setValue( t );
qDebug() << value.toString();
}
PS:如果你想做
qDebug() << value;
您需要在您的自定义类型中实现 QDebug 运算符,并将自定义类型 Token 的此运算符注册到元对象系统。
QMetaType::registerDebugStreamOperator<Token>()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.