2012-05-12 5 views
0

목록과 같은 것을 만들려고합니다. 그러나 목록의 다른 인스턴스는 다른 수의 항목을 가질 수 있으며 입력 유형은 사용자가 제공 한 입력을 기반으로합니다. 예를 들어 사용자는 목록의 각 항목의 구조에 int id, std :: string 이름, double metricA 및 long metricB가 포함되기를 원합니다. 이 입력에 기초하여, 다음이 생성된다가변 크기 및 변수 유형이있는 C++ 컨테이너

struct some_struct { 
    int id; 
    std::string name; 
    double metricA; 
    long metricB; 
} 

list<some_struct> some_list; 

사용자 입력 등이 별도로, some_struct 항목 가변 개수들이있는, 파일에서 화면에 입력을 판독 할 수있다. 즉, 위에 나열된 항목이있을 수도 있고, 2 개만있는 항목이거나 10 개의 완전히 다른 항목이있을 수도 있습니다. 거기에 이런 식으로 구조체를 만들려면 someway 있나요?

또한 some_struct의 각 멤버에 비교 연산자를 적용 할 수 있어야합니다. boost :: any를 사용하여 데이터를 저장할 수는 있지만 비교 연산자와 관련된 문제가 발생하며 이상적인 것보다 많은 오버 헤드가 발생합니다.

+0

왜 목록이 고정 크기가 아니므로 "항목 수"가 중요한지는 분명하지 않습니다. –

+0

누군가가 목록을 사용하지 않고 고정 된 수의 항목 만 지원하는 솔루션을 권장 할 수 있기 때문에 나는 그 말을했습니다. – user396404

+0

이러한 데이터 구조를 만들 수 있다고 가정합니다. 당신은 그걸로 무엇을 할 것입니까? 의사 코드와 같은 C++에서 의도 된 사용 예를 보여줄 수 있습니까? –

답변

0

나는 boost :: variant가있는 목록을 사용했다. 성능은 boost :: any를 사용하는 것보다 훨씬 낫습니다. 그것은 다음과 같이 나타났습니다.

#include <boost/variant/variant.hpp> 
#include <list> 

typedef boost::variant< short, int, long, long long, double, string > flex; 
typedef pair<string, flex> flex_pair; 
typedef list<flex_pair> row_entry; 

list<row_entry> all_records; 
4

C++은 강력 유형 언어이므로 은 데이터 구조 유형을 선언해야합니다. 따라서 임의 숫자 또는 유형의 멤버가있는 struct을 선언 할 수 없으므로 사전에 알려야합니다.

이제 C++에서 이러한 문제를 처리 할 수있는 방법이 있습니다. 몇 가지 이름을하려면

  • 대신 구조의 "표"를 만들기 위해지도 (중 std::map 또는 std::unordered_map)를 사용

    . 문자열을 문자열, 즉 값의 문자열 표현에 이름을 매핑하고이를 마음에 해석합니다.
  • boost::any과 같은 사전 변형 유형을 사용하십시오.
  • 다형성 - 목록에 기본 포인터를 저장하고 값에 대해 가상 메커니즘 디스패치 작업을 호출합니다.
  • 입력 입력 시스템을 입력하십시오. 그런 다음 유형별 값 표를 가지고 목록에서 해당 표를 가리 킵니다.

C++ 프로그래머와 마찬가지로이 작업을 수행하는 방법은 여러 가지가있을 수 있습니다.

2

다양한 멤버가있는 데이터 구조의 문제를 해결하는 데는 여러 가지 방법이 있으며 가장 좋은 방법은 사용 방법에 따라 다릅니다.

가장 확실한 것은 상속을 사용하는 것입니다. 당신은 기본 클래스에서 모든 가능성을 도출 :

struct base_struct { 
    int id; 
    std::string name; 
}; 

list<base_struct*> some_list; 

struct some_struct : public base_struct { 
    double metricA; 
}; 


struct some_other_struct : public base_struct { 
    int metricB; 
}; 

base_struct *s1 = new some_struct; 
s1->id = 1; 
// etc 

base_struct *s2 = new some__other_struct; 
s2->id = 2; 
// etc 

some_list.push_back(s1); 
some_list.push_back(s2); 

까다로운 비트가 당신이 다시 밖으로 요소를 얻을 때, 당신의 경우 적절하게 확인해야한다는 것입니다.type_info 사용하여 주조하기 전에

some_struct* ss = dynamic_cast<some_struct*>(some_list.front()); 

당신은 이름을 조회 할 수 있습니다 : dynamic_cast는 형태 보증 된 방법으로이 작업을 수행 할 수 있습니다

typeid(*some_list.front()).name(); 

주를이 두 일반적으로 OK입니다 RTTI, 건물이 필요하다는 있지만, 특히 RTTI는 성능 비용이 많이 들고, 특히 템플릿이 광범위하게 사용되는 경우 메모리 풋 프린트를 부 풀릴 수 있습니다.

이전 프로젝트에서 우리는 boost any을 사용하여 비슷한 것을 처리했습니다. any의 장점은 서로 파생되지 않은 유형을 혼합 할 수 있다는 것입니다. 돌이켜 보면, 그때까지 유형 검사가 연기되기 때문에 런타임에 오류가 발생하기 쉽도록 코드를 작성했기 때문에 다시 시도 할 수 있을지 확신 할 수 없습니다. . (이뿐만 아니라 dynamic_cast 접근 방식의 사실이다 나쁜 오래된 C 일에서

, 우리는 union이 같은 문제 해결 : 다시

struct base_struct { 
    int id; 
    std::string name; 
    union { // metricA and metricB share memory and only one is ever valid 
     double metricA; 
     int metricB; 
    }; 
}; 

을, 당신은 당신이 처리해야하는 문제가

STL 이전 시대에는 많은 컨테이너 시스템이 을 사용하도록 작성되어 사용자에게 언제 다시 캐스팅해야하는지 알았습니다. 이론적으로 말하면 list<void*>하지만 검색어를 입력 할 방법이 없습니다.

편집 : 절대, void* 방법을 사용하십시오!