Your list addition parameter is a void*
so naturally you'll be flagged with an implicit conversion warning (or error if you're compiling with -Wall -Werror like you should be). Generic implementations of any node management algorithms isn' a trivial as it may seem, and much has been written/coded on the subject.
In your case, you could dynamically allocate the data being added yourself (i.e. allocate an int
and send the resulting address as the void*
, or create additional parameterization of your list interface functions and make them smart enough to figure out what to allocate (if anything)
In general, a generic linked list is eventually not going to escape ownership and sizing information if you're planning on using pointers (and all of the samples linked below go to some lengths to accommodate this). An elaborate enough interface capable of constituting this information into a reasonable node architecture that is generic enough is tedious, but that is the price you pay for generics. Performance is likewise a factor, and again, pay the piper. Type information for a list that holds different data types may also be a consideration, in particular if you're inclined in your algorithms to minimize memory management usage.
There are a multitude of generic linked lists sourced all over this grand illusion we call the World Wide Web. Here are a few such implementations:
PseudoMuto Generic Linked List : Assumes all items are the same size, maintains dynamic storage to them via internal memory management.
CMU Generic Linked List: lecture notes on generics development.
Uncredited Generic List (circa 1999): Another fixed size dynamically managed linked list. Not particularly impressive, but at least functional.
Atachil's Generic Linked List: Yet another generic implementation, this one implemented as a double-linked list.
Plenty more where that came from (google and 10 minutes of filtering out junk).
You needn't reinvent the wheel, but if you want to there are plenty of examples out there that can assist you. A challenge would be implementing a list that
- Takes user-provided allocation/deallocation functions for any memory management requirements
- Uses a
union
internal to thelist_node
that supports all the fundamental data types as well as avoid*
andsize_t
for blob or string data, and of course, a type-identifier so you know what member is the member. - Provides dynamic ownership semantics (i.e. allows the client to specify a dynamic node pointer is "owned" by the client and to not store a duplicate; just use the provided data pointer.
- Bi-directional management (i.e. a double linked list)
Just a few things to consider when embarking on your quest. I wish you the best of luck.