Reputation: 79
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
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
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
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