簡體   English   中英

指向模板類實例的指針的向量

[英]Vector of pointers to instances of a templated class

我正在實現一個任務運行時系統,該系統為用戶提供的各種類型的對象維護緩沖區。 此外,所有對象在存儲到緩沖區之前都已包裝。 由於運行時不知道用戶將提供的對象類型,因此將Wrapper和Buffer類作為模板:

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)每個任務都需要保留對多個緩沖區的引用(此數目在編譯時是未知的)2)緩沖區的類型不同(基於模板化Buffer類)。 3)任務需要使用這些引用來訪問緩沖區。

沒有必要為Buffer類提供基類,然后使用基類指針,因為Buffer類中的WriteRead方法是模板化的,因此不能是虛擬的。

因此,我正在考慮將引用保留為空指針,Task類的外觀類似於:

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指針中獲取有效指針以訪問Buffer。 即,我不知道如何保留buffers [index]指向的對象的類型。

您能幫我這個忙,還是建議其他解決方案?

編輯:緩沖區僅是運行時系統的實現細節,並且用戶不知道它們的存在。

以我的經驗,當用戶類型保留在用戶代碼中時,處理緩沖區的運行時系統無需擔心這些緩沖區的實際類型。 用戶可以在類型化的緩沖區上調用操作。

    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類。

您需要的是所謂的類型擦除。 這是在模板中隱藏類型的方法。

基本技術如下:-具有一個抽象類,該抽象類具有您要在類型獨立的方式中聲明的行為。 -從該類派生您的模板類,實現其虛擬方法。

好消息,您可能不需要自己編寫,這里已經有了boost::any 由於您只需要獲取一個指針並返回該對象,就足夠了。

現在,使用void*是一個壞主意。 正如perreal所提到的那樣,處理緩沖區的代碼不應在乎類型。 要做的一件好事是使用char* 這是緩沖區(例如套接字api)常用的類型。 它比以前也更安全:標准中有一條特殊規則,允許更安全地轉換為char* (請參見別名規則)。

這並不完全是您問題的答案,但我只是想指出您的寫作方式

Wrapper<T> Read() { 

使其成為按值返回的mutator成員函數,因此這不是一個好習慣,因為它會強制用戶編寫異常的不安全代碼。

出於相同的原因,STL stack::pop()成員函數返回void,而不是從堆棧彈出的對象也返回void。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM