2017-02-18 3 views
0

벡터 벡터에 저장된 파생 형식에 액세스하기 위해 템플릿 API를 만들려고합니다. 외부 벡터에는 파생 된 각 유형에 대한 요소가 있습니다. 내부 벡터에는 이러한 유형의 컬렉션이 있습니다.벡터 또는 벡터에 저장된 파생 클래스 개체의 템플릿 API 만들기

std::vector<std::vector<MyBaseClass>* > items; 

궁극적으로 파생 된 유형의 MyBaseClass를 추가하고 액세스 할 수있는 API를 제공하고자합니다 (특수 템플릿없이). 이런 식으로 뭔가 :

T& addItem(size_t index, T& item); 
T& getItem(size_t index); 

사용과 같은 :

AClass : public MyBaseClass {}; 
BClass : public MyBaseClass {}; 

addItem<AClass&>(123, item); 
addItem<BClass&>(456, item); 

AClass& = getItem<AClass&>(123); 
BClass& = getItem<BClass&>(456); 

전문 템플릿의 부족에 대한 이유는 내가 다른 개발자는이 코드를 수정할 필요없이 새로운 파생 된 형식의 사용을 가능하게 할 것입니다 .

그래서 파생 클래스 유형을 알고 코드를 전문화하지 않고도 구현 된 API를 얻을 수있는 방법이 있습니까?

유니온과 템플릿으로이 작업을 수행 할 수 있습니까?

참고 : 내부 벡터는 데이터를 연속적으로 메모리에 저장해야하므로 포인터를 사용하지 않습니다.

참고 : 부스트없이 C++ 11을 사용하고 있습니다.

감사합니다. 아마도 이러한 라인을 따라

+4

'std :: vector '에는 파생 된 유형의 객체를 포함 할 수 없습니다. 기간. – aschepler

+4

'벡터 '에 개체를 추가하면 벡터는 개체의 기본 클래스 부분 만 저장합니다. See [객체 조각이란 무엇입니까?] (http://stackoverflow.com/questions/274626/what-is-object-slicing) –

+0

'std :: vector >'을 사용할 수 있습니다. 그냥'addItem' 포인터에 캐스트를 수행하고 참조를 반환합니다. 잘못된 유형으로 변환하고 잘못된 참조를 반환하는 경우 이는 물론 정의되지 않은 동작입니다. – Cornstalks

답변

0

뭔가 :

class FancyStore { 
public: 
    template <typename T> 
    T& addItem(const T& item) { 
    void*& raw = store_[typeid(T)]; 
    if (!raw) { 
     raw = new std::vector<T>(); 
    } 
    auto v = static_cast<std::vector<T>*>(raw); 
    v->push_back(item); 
    return v->back(); 
    }  

    template <typename T> 
    T& getItem(size_t index) { 
    void* raw = store_[typeid(T)]; 
    auto v = static_cast<std::vector<T>*>(raw); 
    return (*v)[index]; 
    } 

private: 
    std::unordered_map<std::type_index, void*> store_; 
}; 

Live demo. 복사, 소멸자, 오류 처리는 독자의 연습 과제로 남겨 둡니다.

+0

정말 고마워요. 이것은 내가 필요한 것처럼 보입니다. – user1824607

+0

하나의 함수 호출로 모든 벡터의 크기를 조정할 수 있습니까? 비록 런타임까지 타입을 모르더라도? 예 : void resizeItemStore (size_t size); – user1824607

+0

store_를 반복하고 decltype을 사용하여 templated resize 함수를 호출 할 수 있습니까? – user1824607

관련 문제