INI 파일 리더를위한 C ++ 사용자 정의 열거 구조
-
21-08-2019 - |
문제
나는 문자열 레이블과 값이있는 열거를 만들려고 노력하고 있으며 이것을 사용하여 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;
}
};
몇 가지 질문이 있습니다.
더 나은 솔루션을 말해 줄 수 있습니까? 나는 내 자신의 이익을 위해 너무 영리하려고 노력하는지 또는 이것이 실제로 실행 가능한 솔루션인지 확실하지 않습니다.
내 솔루션이 허용되면 누구나 내가 어떻게 일련의 세트를 선언 할 수 있는지 말해 줄 수 있습니다.
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? 그것은 당신이 원하는 것을해야합니다 (그리고 당신이 필요 직접 굴리려면 힌트 소스를 엿볼 수 있습니다).