Удаление общего списка без указателей

У меня есть общий список с шаблоном

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 требует явного упоминания типа; компилятор не может определить тип в своем решении.

Я хотел бы создать вложенный шаблон структуры внутри вашего класса, чтобы помочь:

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

delete на int делает программу некорректной, поэтому компилятор отклонит ее, даже если delete никогда не будет достигнут

То, что вы хотите, возможно, только если вы переключаетесь с "голых" указателей на умные указатели, такие как unique_ptr или же shared_ptr; те, которые управляют памятью для вас, без явного delete,

Другие вопросы по тегам