4

入力からトークンのストリームを生成する字句スキャナーを書いています。これらのトークンにはtypevalueがあります。私は Qt を使用しているので、トークン データを として保存することにしましたQVariant。これは、非カスタム タイプのトークン データに対して非常にうまく機能します。

残念ながら、トークン内に格納されているカスタム タイプもいくつかあります。トークンには、toString()(デバッグ用に) トークンの説明を出力する関数がありますが、カスタム型のデータを持つすべてのトークンに対して、この関数は空の文字列を返します。コードは次のようになります。

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:

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, #)" 

トークンには Test クラスが含まれており、バリアントがそのTT_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ます。(以前にテンプレートソリューションがありましたが、そこで別の問題に遭遇したため、提案されている場合は例が必要です)。

?

4

2 に答える 2

5

実際、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 )これはもちろん、Token へのポインターの代わりに QVariant に Token インスタンスを直接集約することでも可能です (さらに節約できます) 。

Qtフォーラムのこの投稿も参照してください

于 2018-04-06T08:58:35.930 に答える