My C++ is basic but improving and I am trying to use a C++-based development kit (SDK) for some image processing software. The documentation and support for the SDK is limited.

The SDK provides a linked list class and I am keen to utilise this. The class allows me to remove nodes within the list but provides no functions for deleting the data pointed to by the node - that is my responsiblity.

As I intend to have a lot of linked lists, it strikes me as judicious to write my own delete function, rather than have to loop through each list in turn to delete the nodes and the pointed-to data and prevent leaks.

However, in order to do this, I need to pass the type of the data pointed to by the nodes in the list to my function. Is there any way of doing this? Or, is this impossible - hence there being no data delete function with the SDK's class?

I suspect this problem has been addressed before, but part of my problem is that I don't know what phrases to use to search for it. All my searches have come up with rudimentary explanations of linked lists, etc.

Izzy

what kind of functions does that API provide you? createNode, deleteNode etc.? can you post the function signatures here? Are there any functions which return pointer to a node?

Some example function sigs:

void addTail(const type_name *const data) {
	 StdList::addTail((void *)data);
      }

      type_name *getTail() {
	 return ((type_name *)StdList::getTail());
      }

      bool remove(const type_name *const data) {
	 return (StdList::remove((void *)data));
      }

getTail() removes and returns the last element. I intended my delete function have look something like (but the Type type-name bit isn't going to work):

void deleteData(StdList myList, Type type_name){
	type_name *element;
	while (!myList.isEmpty()) {
		element = myList.getTail();
		delete element;
	}
}

Looks to me like a template function waiting to happen.

Google (or search here) for C++ templates they let you write code where types can be arguments. This allows you to write functions similar to what you propose.

Thank you for the hint!

I have created the following template function, I think it works.

template <class type_name>
int deleteData(StdList myList) {
	type_name *element;
	int count = 0;
	while (!myList.isEmpty()) {
		element = (type_name*)myList.getHead();
		delete element;
		count ++;
	}
	return count;
}

I think I've tested it with the one class I am working with currently. Can I be confident that it will work for any class?

In the future, when posting c++ code, please use [code=c++] [/code] around your code.

Are you calling this with something like deleteData<Foo>(foolist); where foolist is a StdList containing objects of type Foo?

If so, I think it will work.

If you were working with other templated classes the type can be implied if you write the function that way. For example the following declaration would allow you to just call deleteData(somevector) where somevector is an instance of the std::vector template.

template <class type_name>
int deleteData(std::vector<type_name> myList) { ... }

Another option, should you be so inclined, would be to develop a template class that wraps their StdList to manage and enforce type for the list. Something along the lines of:

template <class type_name>
class MyStdList : public StdList
{
    // skipping a bunch of other methods
    type_name * getHead() {return (type_name *)StdList::getHead();}

    // I don't know if that have an addTail(), but if they did:
    int addTail(type_name * pObj) {return StdList::addTail(pObj);}

    // You could even at this point, add additional methods
    // say...deleteData?
    int deleteData() {
        type_name *element;
        int count = 0;
        while (!isEmpty()) {
            element = getHead();
            delete element;
            count ++;
        }
        return count;
    }
};

The template then 'knows' what type is supposed to be on the list and will 'prevent' you from putting the wrong thing on. If they have functions that take their StdList, you can pass an instance of the template in that place as it is derived from their list.

Just a thought.

This is great, thank you so much.

Yes, I am calling deleteData<Foo>(foolist) , which works fine.

For completeness, I think I should add that I needed to make a subtle change to my function, because it wasn't actually deleting the original data (just the copy passed to the function, doh!):

template <class type_name>
//int deleteData(StdList myList) {
int deleteData(StdList &myList) { 
	// ...
}

I'm not currently working with other templated classes (I'm sure I will be...), but I'm assuming if I'm working with a mix of variables and classes that your suggestions that would remove the need to specify the data type in the call to deleteData() would require too many version to be written (which rather removes the value of templates)?.

Wrapping their class looks like a robust solution. I think I have achieved it (a template class was already provided that I was able to copy). I now state the type_name in my call to this (something like: foolist=myStdList<Foo>(); ) don't I?

Yes, your change to the deleteData function (to take a reference to the list) would be necessary.

As far as creating an instance of your template list, it would look like: myStdList<Foo> foolist; if declaring a member or a list on the stack. If you wanted the list to come from the heap it would look like: myStdList<Foo> * pfoolist = new myStdList<Foo>(); If you needed to be able to put different kinds of objects on the list, and you had a base class that declared the appropriate interface methods as virtual, you could create a myStdList<BaseClass> myList; and add derived classes to it. The primary problem would be in that anything you access from the list would 'look like' a BaseClass and only have that interface available.

This article has been dead for over six months. Start a new discussion instead.