![](/img/trans.png)
[英]Storing templated object pointers in a vector and accessing through base class pointer
[英]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類中的Write和Read方法是模板化的,因此不能是虛擬的。
因此,我正在考慮將引用保留為空指針,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.