2011-04-11 73 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); }