2011-05-09 3 views
1

현재 열거 형을 사용하여 Base * 배열에 매핑하고 있습니다. 각 Derived 유형에는 enum에 의해 인덱스가 제공됩니다. > TYPENAME지도 - 각 파생 된 유형의 인덱스가 컴파일 타임에 알려져 있기 때문에이기종 포인터 컨테이너

enum DerivedType { 
    DERIVED_TYPE_1 = 0, 
    DERIVED_TYPE_2, 
    ... 
    NUM_DERIVED_TYPES 
}; 


class Base { 

}; 


class Derived1 : public Base { 
    static const DerivedType type; 
}; 
const DerivedType Derived1::type = DERIVED_TYPE_1; 


class Derived2 : public Base { 
    static const DerivedType type; 
}; 
const DerivedType Derived2::type = DERIVED_TYPE_2; 


class Container { 
    Base* obs[NUM_DERIVED_TYPES]; 

    template<class T> 
    void addOb(T* ob) { 
     obs[T::type] = ob; 
    } 

    template<class T> 
    T* getOb() { 
     return (T*) obs[T::type]; 
    } 

    Base* getOb(DerivedType type) { 
     return obs[type]; 
    } 
}; 

, 어쩌면 INT의 유형 이름을보고, 올바른 DerivedN 포인터를 반환 getOb(DerivedType type) 비 템플릿을하는 방법은 무엇입니까 ? 아니면 이런 유형의 패턴을 구현하는 더 좋은 방법이 있습니까? 또한 각 Derived 유형을 색인 구조 값에 할당하는 데이터 구조에 추가하는 것이 좋습니다.

기본적으로 올바른 형식의 Derived *를 반환하면서 형식 또는 인덱스별로 액세스 할 수있는 정적 이질 포인터 컨테이너가 필요합니다. 나는 Boost가 작동 할 것이라고 생각하지만 아직 발견하지 못했습니다.

도움 주셔서 감사합니다.

답변

2

같은 멤버 함수로 구현하고 싶었 경우 어떻게 보일지입니다 100 % 내가 정확하게 질문을 이해하고 있다고 확신하면 아마도및 boost::mpl으로 구현할 수 있습니다. 예를 들어
:

내가 덕분에, 찾고 정확히 무엇
#include <boost/fusion/include/map.hpp> 
#include <boost/fusion/include/at_key.hpp> 
#include <boost/mpl/vector.hpp> 
namespace bf = boost::fusion; 
namespace bm = boost::mpl; 

// This order has to match with the enumerators in DerivedType 
typedef bm::vector< Derived1, Derived2 > DerivedTypes; 

typedef bf::map< bf::pair< Derived1, Derived1* > 
       , bf::pair< Derived2, Derived2* > > Container; 

int main() { 
    Container c(bf::make_pair< Derived1, Derived1* >(0) 
       , bf::make_pair< Derived2, Derived2* >(0)); 
    Derived1 d1; 
    Derived2 d2; 
    bf::at_key<Derived1>(c) = &d1; // access with type 
    bf::at_key<Derived2>(c) = &d2; 
    // access with enum 
    bf::at_key< bm::at_c< DerivedTypes, DERIVED_TYPE_1 >::type >(c) = &d1; 
    bf::at_key< bm::at_c< DerivedTypes, DERIVED_TYPE_2 >::type >(c) = &d2; 
} 
+0

우수한.내가 한 가지 개선 한 점은 벡터에서 맵을 자동으로 채우는 것입니다 :'typedef bm :: fold , bm :: push_back >> :: 컨테이너 유형 : ' – Ryan

+0

고마워, 다행스럽게도 :-) –

0

(1)

불행하게도 불가능 is there a way to have the "non-template" getOb(DerivedType type) return the correct DerivedN pointer. 템플릿이 아닌 함수의 경우 반환 유형은 단일 유형일 수 있으며이 경우에는 Base* 유형이어야합니다. Base* getOb(DerivedType type);의 현재 구현이 적합합니다.

(2) is there a better way to implement this type of pattern?

적어도 당신은 당신을 위해 DerivedType 변수를 초기화한다 (오버 헤드없이) 플릿 중간 클래스를 사용하여 작업을 쉽게 할 수 있습니다. 예를 들어, 다음과 같은 것을 선언

template<DerivedType TYPE> 
struct Link : Base { 
    static const DerivedType type; 
}; 
template<DerivedType TYPE> 
const DerivedType Link<TYPE>::type = TYPE; 

지금 Link<DerivedType>는 파생 클래스를 상속한다, 예를 들면 : 당신이 현재 가지고있는

class Derived1 : public Link<DERIVED_TYPE_1> { 
// no need to declare/define an explicit variable for DerivedType now. 
}; 
0

글쎄, 나에게 꽤 고체 보인다. 내가 보는 유일한 문제는 런타임에 Base* 만 사용할 수 있다는 것입니다. 단일 함수는 1 개의 유형 만 반환 할 수 있기 때문입니다. 당신은 할 수 가짜 기능과 같이 추가 매개 변수를 지정할 필요없이 멀티 타입의 반환을 허용하려면,

// if employed as a free function 
class getOb{ 
    DerivedType _type; 
public: 
    getOb(DerivedType type) 
    : _type(type) {} 

    template<class T> 
    operator T*() const{ 
    Base* ptr; 
    // fetch correct pointer from wherever 
    // using _type, if non-existant use 0 
    return (T*) ptr; 
    } 
}; 

사용

Derived1* pd = getOb(DERIVED_TYPE_1); 
assert(pd != 0); 

매개 변수는 생성자에 전달되는

같은 실제 기능 동안 본문은 변환 연산자에 있습니다. 물론 이것은 단지, 그래서 여기에 무료 서 기능과 좋아 보인다는

class GetObClass{ 
    mutable DerivedType _type; 
public: 
    GetObClass& operator()(DerivedType type) const{ 
    _type = type; 
    return *this; 
    } 

    // template conversion operator as before 
}; 

사용 아니에요하지만

class Container{ 
public: 
    const GetObClass getOb; 
}; 

Container c; 
Derived1* pd = c.getOb(DERIVED_TYPE_1); 
assert(pd != 0);