문제
나는 특정 데이터 소스에 대한 메타 데이터를 저장하는 클래스를 만드는 과정에 있습니다. 메타 데이터는 XML이 구조화되는 방식과 매우 유사한 트리에서 구성됩니다. 메타 데이터 값은 정수, 소수점 또는 문자열 값일 수 있습니다.
C ++에 이와 같은 상황에 대한 변형 데이터를 저장하는 좋은 방법이 있는지 궁금합니다. 변형이 표준 라이브러리를 사용하고 싶으므로 사용 가능한 COM, OLE 및 SQL 변형 유형을 피하고 있습니다.
내 현재 솔루션은 다음과 같은 것 같습니다.
enum MetaValueType
{
MetaChar,
MetaString,
MetaShort,
MetaInt,
MetaFloat,
MetaDouble
};
union MetaUnion
{
char cValue;
short sValue;
int iValue;
float fValue;
double dValue;
};
class MetaValue
{
...
private:
MetaValueType ValueType;
std::string StringValue;
MetaUnion VariantValue;
};
Metavalue 클래스에는 현재 저장된 변형 값을 얻기위한 다양한 get 함수가 있지만, 내가 원하는 값을 파악하기 위해 값에 대한 모든 쿼리를 IF/Else IF IF 문의 큰 블록으로 만듭니다.
또한 값을 문자열로만 저장하고 다른 변형 유형을 얻기 위해 변환을 수행하는 것을 탐색했지만, 내가 보는 한, 내부 문자열 구문 분석 및 오류 처리가 예쁘지 않은 오류 처리로 이어집니다. 플로팅 포인트 값에 대한 정밀도 및 데이터 손실 문제의 큰 오래된 캔이지만 위에 언급 된 문제인 경우 쿼리를 제거하지 않습니다.
표준 라이브러리를 사용하여 C ++ 변형 데이터 유형에 사용하기에 더 깨끗한 것을 구현하거나 본 사람이 있습니까?
해결책
C ++ 17 기준으로 std::variant
.
아직 사용할 수 없다면 원할 수도 있습니다. 부스트. 다형성 모델링을위한 유사하지만 뚜렷한 유형은 std::any
(그리고 C-C ++ 17, boost.any).
추가 포인터처럼삭제를 입력하십시오”.
다른 팁
Konrad의 답변 (기존 표준화 된 솔루션 사용)은 자신의 버그가 발생하기 쉬운 버전을 작성하는 것보다 확실히 바람직하지만 Boost 변형에는 특히 사본 구성 및 메모리에 약간의 오버 헤드가 있습니다.
일반적인 맞춤형 접근 방식은 다음과 같은 수정 된 공장 패턴입니다.
- 객체 유형 (열거)을 캡슐화하거나 'typeid'(선호)를 사용하는 일반 객체에 대한 기본 인터페이스를 만듭니다.
- 이제 템플릿을 사용하여 인터페이스를 구현하십시오
Derived
수업. - 템플릿 화 된 공장 클래스를 만듭니다
create
서명과 기능 :
template <typename _T> Base * Factory::create ();
이것은 내부적으로 a Derived<_T>
힙에 물체를 뿌리고 동적 캐스트 포인터를 재조정합니다. 구현하려는 각 클래스마다 이것을 전문화하십시오.
마지막으로, 정의 a Variant
이것을 포함하는 래퍼 Base *
포인터 및 정의 템플릿 get and set functions. 유틸리티 기능과 같은 기능 getType()
, isEmpty()
, 할당 및 평등 연산자 등은 여기에서 적절하게 구현할 수 있습니다.
유틸리티 기능과 공장 구현에 따라 지원되는 클래스는 할당 또는 사본 구성과 같은 기본 기능을 지원해야합니다.
또한 시스템의 두 배 크기와 사용중인 유형의 열거가있는 더 C-ish 솔루션으로 내려갈 수도 있습니다. 그것은 합리적으로 깨끗하지만 시스템의 원시 바이트에 전적으로 편안하다고 느끼는 사람을위한 솔루션입니다.
C ++ 17은 이제 가지고 있습니다 std::variant
정확히 당신이 찾고있는 것입니다.
질문이 오랫동안 답변되었지만 기록을 위해 나는 그것을 언급하고 싶습니다. QVARIART 또한이 작업을 수행합니다.