2012-02-29 3 views
2

저는 다양한 유형의 사용자 제공 객체에 대한 버퍼를 유지 관리하는 작업 런타임 시스템을 구현하고 있습니다. 또한 모든 오브젝트는 버퍼에 저장되기 전에 랩핑됩니다. ,템플릿 기반 클래스의 인스턴스에 대한 포인터 벡터

template <typename T> 
class Wrapper { 
private: 
    T mdata; 
public: 
    Wrapper() = default; 
    Wrapper(T& user_data) : mdata(user_data) {} 
    T& GetData() { return mdata; } 
    ... 
}; 

template <typename T> 
class Buffer { 
private: 
    std::deque<Wrapper<T>> items; 
public: 
    void Write(Wrapper<T> wd) { 
     items.push_back(wd); 
    } 

    Wrapper<T> Read() { 
     Wrapper<T> tmp = items.front(); 
     items.pop_front(); 
     return tmp; 
    } 
    ... 
}; 

지금, 런타임 시스템이 작업을 처리하는 각각의 부분 집합에서 작동 : 런타임 사용자가 제공 할 객체의 유형을 알고하지 않기 때문에, 래퍼와 버퍼 클래스는 템플릿된다 전술 한 버퍼. 따라서, 각 버퍼는 하나 이상의 태스크에 의해 동작된다. 이는 태스크가 버퍼를 공유 할 수 있기 때문에 태스크가 버퍼에 대한 참조를 유지해야 함을 의미합니다. 내 문제가 어디에

이입니다 1) 각 작업 (이 번호는 컴파일 시간에 알 수없는) 버퍼가 templeted 버퍼 클래스를 기반으로 (다른 종류의 수 있습니다 2) 버퍼의 수에 대한 참조를 유지하기 위해 필요). 3) 작업은 이러한 참조를 사용하여 버퍼에 액세스해야합니다.

이 버퍼 클래스에 대한 기본 클래스를 가지고 아무 소용이 없다 후 가상 수 없습니다, 따라서 templeted하는 버퍼 클래스 및 읽기 쓰기 방법부터 기본 클래스 포인터를 사용합니다.

그래서 나는 작업 클래스는 같이 보일 것입니다 무효 포인터로 참조를 유지하기 위해 생각했다 :

class Task { 
private: 
    vector<void *> buffers; 
public: 
    template<typename T> 
    void AddBuffer(Buffet<T>* bptr) { 
     buffers.push_back((void *) bptr); 
    } 

    template<typename T> 
    Buffer<T>* GetBufferPtr(int index) { 
     return some_way_of_cast(buffers[index]); 
    } 
    ... 
}; 
이 가진 문제는 내가에서 유효한 포인터를 얻는 방법을 모르겠입니다

void 포인터를 사용하여 버퍼에 액세스합니다. 즉, 버퍼 [index]이 가리키는 개체의 형식을 유지하는 방법을 알지 못합니다.

이 문제를 해결하거나 다른 해결책을 제안 할 수 있습니까?

EDIT : 버퍼는 런타임 시스템의 구현 세부 사항 일 뿐이며 사용자는 자신의 존재를 인식하지 못합니다.

+0

흠, 템플릿으로는 잘 작동하지 않을 것입니다. 너무 많은 런타임 다형성이 필요합니다. 내 머리에서 두 가지 옵션을 제안 할 것입니다 : 1. 하위 유형 다형성을 사방에 사용하고 사용자가 'Task' 클래스에 필요한 모든 것을 제공하는 일반적인 추상 기본 클래스에서 자신의 유형을 상속 받도록하십시오. 2. 부스트. 왜. 그러나 둘 다 정말 만족스럽지 않습니다. – Philipp

+0

@Philipp 나는 시스템이 작동하도록 의도 했으므로 사용자는 작업 영역을 정의하고 각 작업에 특별한 관심을 갖는 변수를 선언한다는 점에서 일반 프로그램과 다른 프로그램을 작성해야합니다. 이러한 변수는 Wrapper 템플릿을 사용하여 래핑되어야하며, 이는 선택적 컴파일 타임 및/또는 런타임 검사를 지원합니다. 따라서 사용자가 코드를 더욱 복잡하게 만드는 것을 원하지 않습니다. 대신 나는 그것을 숨기고 싶다. 그리고 당분간 부스트를 피하고 싶습니다. – Diggy

+0

@perreal 기본적으로 작업 실행이 시작되면 관련 버퍼 각각에서 단일 개체를 가져와야합니다. 예를 들어, * GetBufferPtr * 함수의 * some_way_of_cast *. 런타임은 데이터 자체에 신경 쓰지 않아도되지만, 문제는 내가 임의의 수의 버퍼 참조를 가지고 있으며 각 버퍼가 임의의 유형의 데이터를 저장한다는 것입니다. 나는 작업 클래스에서 이것을 인코딩하는 방법을 찾고있다. – Diggy

답변

1

내 경험에 따르면 사용자 유형이 사용자 코드에 보관 될 때 버퍼를 처리하는 런타임 시스템은 이러한 버퍼의 실제 유형에 대해 걱정할 필요가 없습니다. 사용자는 유형이 지정된 버퍼에서 조작을 호출 할 수 있습니다.

class Task { 
    private: 
     vector<void *> buffers; 
    public: 
     void AddBuffer(char* bptr) { 
      buffers.push_back((void *) bptr); 
     } 

     char *GetBufferPtr(int index) { 
      return some_way_of_cast(buffers[index]); 
     } 
     ... 
    }; 

    class RTTask: public Task { 
    /* ... */ 
    void do_stuff() { 
    Buffer<UserType1> b1; b1Id = b1.id(); 
    Buffer<UserType2> b2; b2Id = b2.id(); 

    AddBuffer(cast(&b1)); 
    AddBuffer(cast(&b2)); 
    } 
    void do_stuff2() { 
    Buffer<UserType1> *b1 = cast(GetBufferPtr(b1Id)); 
    b1->push(new UserType1()); 
    } 
}; 

이러한 경우 캐스트는 사용자 코드에 있습니다. 그러나 아마도 당신에게는 다른 문제가 있습니다. 또한 포인터로 전환 할 수있는 경우 Wrapper 클래스가 필요하지 않을 수도 있습니다.

+0

사실, 사용자는 버퍼를 인식하지 못합니다. Wrapper 템플릿 만보고이를 사용하여 시스템에서 "특별한"역할을하는 변수를 구별합니다. 나는 이것을 명확히하기 위해 나의 질문을 편집 할 것이다. – Diggy

0

필요한 것은 유형 삭제라고하는 것입니다. 그것은 템플릿의 유형을 숨기는 방법입니다.

기본 기술은 다음과 같습니다. - 유형 독립적 인 관리자에서 원하는 동작으로 추상 클래스를 만듭니다. - 클래스에서 템플릿 클래스를 파생시키고 가상 메서드를 구현합니다.

좋은 소식은 이미 자신의 글을 쓸 필요가 없습니다. boost::any 이미 있습니다. 필요한 것은 포인터를 얻고 객체를 되 찾는 것입니다. 그러면 충분합니다.

void*으로 작업하는 것이 좋습니다. Perreal이 언급했듯이, 버퍼를 다루는 코드는 타입을 신경 써서는 안된다. 좋은 일은 char*으로 작업하는 것입니다. 이것이 버퍼에 일반적으로 사용되는 유형입니다 (예 :소켓 API). 표준보다 더 안전합니다. char* (더 자세한 내용은 별칭 규칙 참조)으로의보다 안전한 변환을 허용하는 특별한 규칙이 있습니다. 이다

+0

"해당 클래스에서 템플릿 클래스를 파생시키고 가상 메서드를 구현하십시오." -하지만 내 방법은 템플릿이며 그래서 가상 수 없습니다. 이 문제를 해결할 방법이 있습니까? 그렇다면 예제를 제공해 줄 수 있습니까? – Diggy

+0

가상 템플릿이 아닌 메소드를 호출하는 가상 클래스가 아닌 메소드를 기본 클래스에 포함 할 수 있습니다. –

0

이 정확하게 질문에 대한 답변 아니지만, 난 그냥 방법은 당신이

Wrapper<T> Read() { 

가 같은 값으로 반환하고, 뮤 테이터 멤버 함수하게 쓴 것을 지적하고 싶었 사용자가 안전하지 않은 안전 예외 코드를 작성하도록 강제하는 것은 좋지 않습니다.

동일한 이유로 STL stack::pop() 멤버 함수는 스택에서 튀어 나온 개체가 아니라 void를 반환합니다.

+0

그게 유효한 지적이지만, 언급 한대로 대답이 아니므로 주석을 사용하는 것이 더 적절합니다. –

관련 문제