2012-12-13 4 views
1

질문은 MS Visual C++ 11에서 개발 된 코드로 부스트가없는 STL에만 액세스 할 수 있습니다.템플릿이 다른 객체를 STL 컨테이너에 저장하는 방법

약이 헤더로, 래퍼 템플릿 클래스가 :

template <typename Payload> 
class Wrapper { 
    Payload p; 
    std::string src; 
    Wrapper(std::string, Payload); 

    Payload get();  // returns payload 
    void set(Payload); // replaces payload 
    void operator()(); // uses payload 
} 

Payload 아무것도 할 수있다 - 포인터, INT, 심지어 무거운 물체.

나중에 은 std::vector과 같은 컨테이너에 있어야하지만 특정 매개 변수 유형과 관계 ​​없습니다. 그리고 컨테이너가 균질 한 요소를 필요로하기 때문에 그것이 나에게 문제가된다. 제안 패턴에 사용되는 경우 요소의 기본 클래스처럼 보이기 때문에 벡터에서 사용할 때 그 캐스팅이 필요 (?) -

나는, 그러나 그것은 나에게 방법 get()set() 몇 가지 문제를 제공, 기본 클래스 제안 like this from KennyTM을 시도 그 대답.

+1

부스트를 피할 수 있도록 직접 구현할 수있는'boost :: any'와 같은 타입 소거 클래스가 필요합니다. – Nawaz

+1

KennyTM 솔루션은 실제로 가상 기능을 사용할 수있는 경우에만 적용됩니다. 함수의 반환 유형이 호환되지 않기 때문에 여기서는 사용할 수 없습니다. 또한 개체가 템플릿 매개 변수에 따라 달라지는 것은 중요하지 않습니다. 그것들은 여전히 ​​크기가 다른 구별되는 유형이며 컨테이너에서 가장 중요한 것입니다. – pmr

답변

3
template<typename Payload> 
struct Wrapper; 

struct WrapperBase { 
    std::string src; 
    WrapperBase(std::string s):src(s) {} 
    template<typename Payload> 
    Payload get() const; 
    template<typename Payload> 
    void set(Payload); 
    virtual void operator()() = 0; // uses payload 
}; 

template <typename Payload> 
struct Wrapper { 
    Payload payload; 
    Wrapper(std::string s, Payload p):WrapperBase(s),payload(p) {} 

    Payload get() const { return payload; };  // returns payload 
    void set(Payload p) { payload = p; }; // replaces payload 
    virtual void operator()() override; // todo 
} 

template<typename Payload> 
Payload WrapperBase::get() const { 
    Assert(dynamic_cast<Wrapper<Payload> const*>(this)); 
    return static_cast<Wrapper<Payload> const*>(this)->get(); 
} 
template<typename Payload> 
void WrapperBase::set(Payload p) { 
    Assert(dynamic_cast<Wrapper<Payload>*>(this)); 
    static_cast<Wrapper<Payload>*>(this)->set(p); 
} 

사용자, 페이로드의 유형이 무엇인지 알 필요가있다. dynamic_cast<Wrapper<Payload>*>을 사용하면 알 수없는 경우 주어진 WrapperBase이 특정 종류인지 파악할 수 있습니다.

값 의미가 없으므로 실제 인스턴스가 아닌 WrapperBase에 스마트 포인터 vector을 저장해야합니다. std::shared_ptr 또는 std::unique_ptr은 매우 다른 동작을하는 좋은 후보입니다.

유한 경계 집합이 Payloads 인 경우 방문자 패턴이 작동 할 수 있습니다.

값 의미가 필요한 경우 실제 페이로드를 저장하는 pImpl 패턴은 수동 operator=을 사용하여 pImpl을 복제 할 수 있습니다.

"do you hold type T"이라고 할 수는 있지만 일반적으로 dynamic_cast과 유사합니다.

+0

흥미 롭습니다. 그래서 저는 기본 클래스의 메소드 템플릿을 놓쳤습니다. 고맙습니다, 지금 시도하십시오. –

5

그런 이유로 당신은 어떤 종류의 유형 삭제를 사용해야 할 것입니다. 가장 기본적인 (기본 유형을 제공하고, 포인터를 기준으로 요소를 저장) 부스트와 같은 더 멋진 솔루션 : : 당신이 선택할 수있는 모든 것 (나는 부스트를 언급하지 않았지만 항상 구현을 살펴볼 수 있음) . 또는 페이로드 세트가 알려져 있고 상대적으로 작지만 단일 용도로 구현하기가 어려울 경우 변형 접근 방식 (boost :: variant와 유사)을 사용할 수 있습니다. 그들이 설정/페이로드를 얻을하려는 경우 WrapperBase

관련 문제