0

文字列ラベルと値を持つ列挙型を作成しようとしていますが、これを使用してiniファイルからデータを読み取る予定です。

たとえば、iniファイルでは、値のタグ/名前の前にいくつかの値またはタイプ値がある場合がありdoubleますintstring

SomeFloat = 0.5
SomeInteger = 5
FileName = ../Data/xor.csv

ファイルからタグを読み取ると、それはとして入ってくるstringので、すべての値を保持したいstd::setのですが...タグを読み取ると、それをと比較することができEnumType、ラベルと一致する場合は、タイプをチェックして適切な変換を行います(atoiまたは文字列を使用するなど)

例えば:

EnumType<int>     someInteger;
someInteger.label = "SomeInteger";
someInteger.type = INT;

std::set<EnumType> myValues;
//
// populate the set
myValues.insert(someInteger);
//

void ProcessTagAndValue(const std::string &tag, const std::string &value)
{
    switch(myValues[tag].type)
    {
    case INT:
        myValues[tag].value = atoi(value);
        break;
    case DOUBLE:
        //
        break;
    case STRING:
        myValues[tag].value = value;
        break;
    default:
        break;
    }
}

enum ValueType{INT,DOUBLE,STRING];

template <class T>
struct EnumType{
    std::string label;
    ValueType   type;
    T           value;

    bool operator==(const EnumType &other) const {
        return this->label == other.label;
    }

    bool operator==(const T& other ) const
    {
        return this->value == other;
    }

    T& operator=(const T& p)
    {
        value = p;
        return value;
    }

    EnumType& operator=(const EnumType& p)
    {
        if (this != &p) {  // make sure not same object
            this->label = p.label;
            this->value = p.value;
        }
        return *this;
    }
};

いくつか質問があります。

  1. もっと良い解決策を教えてもらえますか?自分の利益のために賢くなりすぎているのか、それともこれが本当に実行可能な解決策なのかはわかりません。

  2. 私の解決策が受け入れられる場合std::set<EnumType<...>>、列挙型が値に使用するタイプを実際に知らなくても、任意のタイプ(int、double、string)を受け入れることができるように、セットを宣言する方法を誰かに教えてもらえますか?

あなたがコードを持っているなら、それは素晴らしいでしょう!:)

4

2 に答える 2

1

Boost.Anyを見たことがありますか?それはあなたが望むことをするはずです(そしてあなたがあなた自身を転がす必要があるならば、あなたはヒントのためにソースを覗くことができます)。

于 2009-05-12T22:16:13.810 に答える
1

タイプのセットが限られていて非常に安定している場合は、Boost.Variantを使用できます。後で新しいタイプのサポートを追加する場合は、この方法を忘れた方がよいでしょう。この状況では、 Boost.Anyに基づくソリューション、または文字列のペアの方が適しています。

typedef boost::variant<int, double, std::string> ValueType;
struct EnumType {
std::string label;
ValueType value;
};

もう1つの質問は、「これらの値は後でどのように使用されるのか」です。「SomeInteger」を関数に渡してintを受け入れる場合でも、次のようなコードを実行する必要があります。

acceptInt( get<int>( v.value ) ); // get may throw

このアプローチは、固定されたタイプのセットを均一に処理する場合に適しています。

class processValue : public boost::static_visitor<>
{
public:
    void operator()(int i) const
    {
        acceptInt( i );
    }
    void operator()(double d) const
    {
        acceptDouble( d );
    }
    void operator()(const std::string & str) const
    {
        acceptString( str );
    }
};
boost::apply_visitor( processValue(), v.value );
于 2009-05-12T22:58:53.460 に答える