Generic list deleting non pointers

I have a generic list with a template

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;

        }
    }
};

The important part is the isDelete
This is only a sample code

I need this because I want to store data like this:

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

and also

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

The problem if I store only <int> the compiler said that I cannot delete non pointer variables, but I don't want to in this case. How can I solve this?
when I store <int*> there is no compiler error...

Upvotes: 0

Views: 1123

Answers (3)

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361322

Without changing much your code, I would solve your problem as

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;
       }
   }
};

EDIT: I just noticed that @ildjarn has provided similar solution. However there is one interesting difference: my solution does NOT require you to mention the type of data when calling the function template; the compiler automatically deduces it. @ildjarn's solution, however, requires you to mention the type explicitly; the compiler cannot deduce the type in his solution.

Upvotes: 3

ildjarn
ildjarn

Reputation: 62975

I would create a nested struct template inside your class to help:

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

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

Then change the line that was using isDelete from

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

to

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

Upvotes: 1

Fred Foo
Fred Foo

Reputation: 363517

delete on an int makes a program ill-formed, so the compiler will reject it, even though the delete would never be reached.

What you want is only possible if you switch from "bare" pointers to smart pointers such as unique_ptr or shared_ptr; those handle memory management for you, without explicit delete.

Upvotes: 0

Related Questions