문제

나는 문자열 레이블과 값이있는 열거를 만들려고 노력하고 있으며 이것을 사용하여 INI 파일에서 내용을 읽을 계획입니다.

예를 들어 INI 파일에 일부가있을 수 있습니다. double, int 또는 string 값의 태그/이름이 우선하는 유형 값 :

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)을 허용 할 수 있도록?

코드가 있다면 좋을 것입니다! :)

도움이 되었습니까?

해결책

제한적이고 안정적인 유형 세트가 있다면 부스트 사용될 수있다. 나중에 새로운 유형에 대한 지원을 추가하려면이 방법을 잊어 버리십시오. 이 상황에서 해결책을 기반으로합니다 boost.any, 또는 한 쌍의 문자열이 더 좋을 것입니다.

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

또 다른 질문은 "이러한 값이 나중에 어떻게 사용될 것인가?"입니다. int를 수락하기 위해 "someInteger"를 통과하려는 경우 여전히 다음과 유사한 코드를 실행해야합니다.

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 );

다른 팁

당신은 보셨습니까? boost.any? 그것은 당신이 원하는 것을해야합니다 (그리고 당신이 필요 직접 굴리려면 힌트 소스를 엿볼 수 있습니다).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top