2011-04-11 23 views
0

我有一個通用的清單與模板通用列表中刪除非指針

template<class t> 
class GenericList { 
    //the data is storeed in a chained list, this is not really important. 
    struct c_list { t data; c_list* next; ...constructor... }; 

public: 
    bool isDelete; 
    GenericList() : isDelete(false) {...} 

    void add(t d) { 
     c_list* tmp = new c_list(d, first->next); 
     //this is not really important again... 
    } 

    ~GenericList() { 
     c_list* tmp = first; 
     c_list* tmp2; 
     while(tmp->next!=NULL) { 
      if (isDelete) { delete tmp->data; } //important part 
      tmp2=tmp->next; 
      delete tmp; 
      tmp=tmp2; 

     } 
    } 
}; 

的重要組成部分,是isDelete
這僅僅是一個示例代碼

我需要這個,因爲我想要存儲這樣的數據:

GenericList<int> list; 
list.add(22);list.add(33); 

GenericList<string*> list; 
list.add(new string("asd")); list.add(new string("watta")); 

如果我儲存的問題只<int>編譯器說,我不能刪除非指針變量,但我不希望在這種情況下。我該如何解決這個問題?
當我存儲<int*>沒有編譯器錯誤...

回答

3

在不改變行很多你的代碼,我會解決你的問題爲

template<class t> 
class GenericList 
{ 
    //same as before 

    //add this function template 
    template<typename T> 
    void delete_if_pointer(T & item) {} //do nothing: item is not pointer 

    template<typename T> 
    void delete_if_pointer(T* item) { delete item; } //delete: item is pointer 

    ~GenericList() { 
     c_list* tmp = first; 
     c_list* tmp2; 
     while(tmp->next!=NULL) { 
      delete_if_pointer(tmp->data); // call the function template 
      tmp2=tmp->next; 
      delete tmp; 
      tmp=tmp2; 
     } 
    } 
}; 

編輯:我只注意到@ildjarn提供類似的解決方案。但是有一個有趣的區別:我的解決方案不需要在調用函數模板時提及data的類型;編譯器自動推斷它。但是,@ ildjarn的解決方案需要您明確提及類型;編譯器不能在推導出他的解決方案中的類型。

+1

確實有效。感謝您的快速回答。 – 2011-04-11 17:53:53

+0

@ildjarn:我正在使用'&'。這足以避免複製! – Nawaz 2011-04-11 18:12:34

0

deleteint使得程序形成不良的,所以編譯器會拒絕它,即使delete永遠不會達到。

只有當您從「裸」指針切換到智能指針(如unique_ptrshared_ptr;那些爲你處理內存管理,沒有明確的delete

1

我會創造你的類中的嵌套結構模板的幫助:

template<typename U> 
struct deleter 
{ 
    static void invoke(U const&) { } 
}; 

template<typename U> 
struct deleter<U*> 
{ 
    static void invoke(U* const ptr) { delete ptr; } 
}; 

然後更改所有正在使用isDelete

if (isDelete) { delete tmp->data; } 

if (isDelete) { deleter<t>::invoke(tmp->data); }