I am not sure that what I am trying to do is called encapsulation, but it's an OOP concept. I am implementing a binary tree and in particular the insert function:
typedef struct __node* tree;
typedef struct __node { void* data; tree l,r; } node;
typedef struct {int (*cmp)(void* a,void* b); tree root;} avl_tree;
....
void tree_insert(tree node, tree* root, int (*cmp)(void* a,void* b))
{
if (*root==NULL) { *root=node; return; }
int c1 = cmp(node->data, (*root)->data);
if (c1==-1) tree_insert(node, &((*root)->l), cmp);
}
tree tree_new_node(void*data){ tree a = malloc(...); ... return a; }
void avl_insert(void* data, avl_tree* a)
{
tree_insert(tree_new_node(data), &(a->root), a->cmp);
....
}
The module is to be used through the avl_insert
function which is given a pointer to the relevant balanced tree avl_tree
which contains the pointer to the raw tree as well as a pointer to comparator. Now, it should obviously call tree insert
and tree_insert
should have access to the comparator as well as to the node I am currently inserting. The function walks on a binary tree so it's naturally recursive. However, if I give it the comparator and the current node as parameters they will be passed with each recursive invocation which is not necessary since they will always be the same.
I would like to avoid having to do so. I have not been able to come up with a clean and nice solution. These are the options that I could think of:
Use a C++ class and have the
tree_insert
function be a method ofavl_tree
class. Then it would have access to the comparator through thethis
pointer. The problem with this solution is that I want to use C not C++. Besides, it won't eliminate the passing of the current node parameter.Use static members inside the function (or global data). I am not sure I can cleanly initialize them at each
avl_insert
call. Besides, this solution is not thread safe.
Now that I think about it this seems very easy to implement in a functional programming language. I wonder, is this a fundamental problem with C or is it just me not knowing how to do it. What would be the cleanest way to achieve this?
Thank you!
After I thought about Victor Sorokin's answer I read about the this
pointer and it turns out it is an implicit parameter in every member function call. Now that I think about it it seems the only logical solution. Each invocation of the tree_insert
function needs to know the address of the structure it's operating on. Not even in a functional language could you avoid that extra pointer...
A possible solution would be to keep a pointer to the main tree structure in each node..
So it's a fundamental "problem".