Thomas789
Thomas789

Reputation: 79

Compiler error trying to delete template type which is a pointer

I'm new to C++ and I have the ambition to understand how templates work. So I have implemented a generic list MyList which may contain both built-in primitive types and pointers. In the remove function I want to distinguish pointer types and built-ins so I can delete the object behind the pointer but leave the built-ins untouched.

To distinguish the template types, which can be pointers or non-pointers, I wrote the following functions, which work fine:

// distinguish between pointer and non-pointer type of template variable
template<typename T> bool is_pointer(T t) {
    return false;
}

template<typename T> bool is_pointer(T* t) {
    return true;
}

In the list function remove the idea was to test for pointers and delete them in case. However, the delete statement does not compile:

template<typename T> void MyList<T>::remove() {
    ...
    if (is_pointer(temp->getContent())) {
        // delete object pointer points to
        T t = temp->getContent();
        cout << t;    // prints out address
        // delete t;  // produces compiler error (see below)
}

In the main.cpp I test the list class with various types, I call amongst others:

MyList<int> mylist;                // with type int
mylist.remove();
mylist.add(3);
// add and remove elements

MyList<string> mylist2;           // with type string
...

MyList<string*> mylist3;          // with type string*
mylist.add(new string("three")); 
mylist.remove();

When I comment out the statement delete t; I can verify that the control flow is correct: the if-statement is only entered for the string* example. However, if I uncomment the delete statement the compiler complains like that:

../mylist.h: In member function ‘void MyList<T>::remove() [with T = int]’:
../main.cpp:36:18:   instantiated from here
../mylist.h:124:6: error: type ‘int’ argument given to ‘delete’, expected pointer
../mylist.h: In member function ‘void MyList<T>::remove() [with T = std::basic_string<char>]’:
../main.cpp:71:18:   instantiated from here
../mylist.h:124:6: error: type ‘struct std::basic_string<char>’ argument given to ‘delete’, expected pointer
make: *** [main.o] Error 1

What is it that I don't see? I'm using the delete statement on pointers only but still I get these compiler errors. If I print out t in the if-statement it is a pointer address!

Upvotes: 1

Views: 2572

Answers (3)

anonymous
anonymous

Reputation: 1968

I suggest to use C++ 11 type_traits and auto_ptr like this

#include <type_traits>
template<typename T> void MyList<T>::remove() {
    ...
    if (is_pointer(T)) {
        // delete object pointer points to
        T t = temp->getContent();
        cout << t;    // prints out address
        auto_ptr tempobj(T);
}

Also look at this Determine if Type is a pointer in a template function that could be useful incase your compiler is not C++ 11 compliant.

Thanks Niraj Rathi

Upvotes: 0

Henrik
Henrik

Reputation: 23324

If you instantiate the template with T = int, you get:

void MyList::remove() {
    if (false) {
        T t = temp->getContent();
        cout << t;
        delete t;
    }
}

Even if the code block is never executed, it must be syntactically correct.

Upvotes: 0

Marius Bancila
Marius Bancila

Reputation: 16328

A template is a blueprint that the compiler uses to actually create types based on the use of the blueprint. When you use you template with int and string* the compiler will actually create two variations of MyList, replacing T with the actual type. The implementation that uses int for T is bogus, because deleting an int does not make sense. The actual code the compiler generates is

int t = temp->getContent();
cout << t;
delete t;

This is incorrect, as you could figure out.

Upvotes: 1

Related Questions