2013-07-19 5 views
1

나는 boost::anyboost::variant을 잘 알고 있지만,이 경우에는 내 필요에 맞지 않습니다.모든 컨테이너 구현

일반적으로 알 수없는 유형의 객체를 포함하려면 공통 기본에서 객체를 추출하고 가상 메소드를 통해 인스턴스에 액세스합니다. 그러나 공통 기반을 사용하는 것이 불가능하다면 무엇을 할 수 있습니까?

이 예에서 포함 된 유형을 알고 있어야하지만 나와 함께 견뎌야한다는 것을 알고 있습니다. std::vector은 최상위 클래스도 템플릿이되는 템플릿 클래스입니다. 내가 아는 한 STL 헤더를 수정하지 않고 템플릿이 아닌 기본 템플릿을 제공 할 수는 없습니다. 이제 단일 유형의 벡터를 만들고 싶지만 포함하는 클래스는 형식을 신경 쓰지 않지만 'common'메서드 중 일부 (예 : size()pop_back())에 액세스해야합니다.

boost::any을 사용하면 형식이 지워져서 포함 된 개체를 역 참조 할 수 없게됩니다. boost::varianttuple은 어떤 유형이 삽입 될 수 있는지 알고 있어야하며, 포함하는 클래스 자체가 템플릿이됩니다.

struct container 
{ 
    virtual ~container() = 0; 
    virtual void pop_back() = 0; 
    virtual size_t size() = 0; 
    ... 
} 
template < typename T > 
struct contained 
{ 
    std::vector<T> _vec; 
    contained (size_t n, T _what) : _vec(n, _what) {} 
    virtual void pop_back() { _vec.pop_back(); } 
    ... 
} 
class some_class 
{ 
    container* _cont; 
    template < typename T > 
    void create (T _first) { _cont = new contained<T>(1,_first); } 
    ... 
} 

여기 클라이언트가 create()에 호출 할 수 및 템플릿 매개 변수가 자동으로 결정되어야한다 : 나는 지금까지 무엇을 가지고

이 같은 것입니다. 내가 아는 좋은 예는 아니지만 클라이언트에서 템플릿 매개 변수를 숨기려고합니다. 이렇게하지 않으면 some_class도 저장되는 유형을 추적해야합니다.

내 메서드는 특히 내부 클래스에 자체적 인 가상 메서드가있는 경우 성능 손실을 발생시키는 가상 호출을 사용합니다.

내 요구 사항에 더 적합한 다른 유형의 용기가 있습니까?

이상적으로, 나는 그것이 유형을 추적하고 간단한 캐스트를 할 것이 아니라 가상의 방법에 의존하는 것 내부적으로

container = std::vector<T>; 
container.pop_back(); 
container.push_back(T2); // compile error if types don't match 

같은 것을하고 싶습니다. 거의 auto과 비슷한 점은 일단 선언되면 유형이 변경 될 수 있다는 것입니다.

편집 :

현실에서, 나는 std::basic_filebuf 주위에 래퍼를 만들려고합니다. 이 래퍼 클래스는 BOM을 기준으로 char, wchar_t 또는 unsigned long의 파일을 엽니 다. 랩퍼는 클라이언트가 선택하는대로 템플릿 매개 변수가있는 basic_filebuf에서도 파생됩니다. 내부적으로는 파일의 유니 코드 코드 포인트를 원하는 인코딩으로 변환합니다. 이 문제는 내부 변수 basic_filebuf을 저장할 때 발생합니다. 이는 템플릿 매개 변수로 모든 유형으로 선언 될 수 있기 때문입니다. 나는 클라이언트가 자신의 basic_filebuf 인스턴스를 전달할 수 있기를 원하기 때문에 템플릿 전문화를 사용하고 싶지 않습니다.

VS2010 호환 가능해야하며 C++ 11의 기능이 제한적입니다.

+0

어떤 문제 당신은이 작업을 수행 할 필요가 어디에 해결하기 위해 노력하고있다? – GManNickG

+0

@GManNickG 한 예는 어떻게 내부 유형에 대한 배려없이 해당 서식 파일을 저장하는 것입니다 ... 요소의 형태는'int' wchar_t''char''이 될 수있는 표준 스트림 클래스 것입니까? 'std :: string'과'std :: wstring'은 어떨까요? 거의 동일하지만 약간 다른 처리가 필요합니다. – Twifty

+1

죄송합니다. 따라 가지 않습니다. 내 말은 결국 프로그램이 결국 * 할거야? – GManNickG

답변

0

컴파일 타임 형식 검사와 함께 사용할 수 없습니다.당신의 "이상적"예를 바탕으로 :

template<typename FILEBUF> 
void gensputc(FILEBUF* fb, long long c) { 
    FILEBUf::char_type c2 = smart_convert<FILEBUf::char_type>(c); 
    fb->sputc(c2); 
} 

class FileBufWrapper { 
public: 
    template<typename FILEBUF> FileBufWrapper(FILEBUF* fb) { 
    fb_ = fb; 
    sputc_ = gensputc<FILEBUF>; 
    } 
    void sputc(long long c) { 
    sputc_(fb_,c); 
    } 
private: 
    typedef void(*sputc_t)(void*, long long); 
    sputc_t sputc_; 
    void* fb_; 
}; 

는 smart_convert 함수는 런타임 예외의 경우를 오류 : filebuf 케이스

container c; 
if (thingKnownAtRunTime()) { 
    c = vector<int>; 
} else { 
    c = vector<string>; 
} 
c.push_back("hello world"); 

하지만, 당신은 (테스트되지 않은 경고) 같은 뭔가 충분 얻을 수 있습니다 값을 char 유형으로 변환 할 수 없습니다. 또한이 기능은 호출하려는 모든 기능에 대해 수행해야합니다. 당신은 11의 표준 : 기능과 표준 : : 바인드 C++에 액세스 할 수있는 경우

이 특히 당신은 아무것도를 변환 할 필요가없는 경우에, 조금 청소기를 만들 수 있습니다.