I’m trying to implement a binary search tree class, but the compiler is throwing errors. The bstNode.h file is here:
template <class Item, class Key>
class bstNode
{
public:
bstNode();
bstNode(const Item& init_data, const Key& init_key, bstNode<Item, Key> *init_left, bstNode<Item, Key> *init_right);
~bstNode();
bstNode<Item, Key>* tree_copy(const bstNode<Item, Key>*& root);
private:
Item data;
Key key;
bstNode* left;
bstNode* right;
};
template <class Item, class Key>
//line 83 in the original code is below
bstNode<Item, Key>* bstNode<Item, Key>::tree_copy(const bstNode<Item, Key>*& root)
{
bstNode<Item, Key>* l_ptr;
bstNode<Item, Key>* r_ptr;
if (root == NULL) return NULL;
l_ptr = tree_copy(root -> left());
r_ptr = tree_copy(root -> right());
return new bstNode<Item, Key> (root -> data(), l_ptr, r_ptr);
}
The .h file compiles fine with an empty main function, but when I try it with the following bit of code in bstNode.cxx, it crashes, giving an error. The code is:
#include <cstddef>
#include <algorithm>
#include <math.h>
#include <iostream>
#include "bstNode.h"
using namespace std;
int main()
{
bstNode<int, size_t>* root_ptr = NULL;
bstNode<int, size_t>* copy_root_ptr = root_ptr -> tree_copy(root_ptr);
return 0;
}
And the error is:
bstNode.cxx: In function ‘int main()’:
bstNode.cxx:14: error: no matching function for call to ‘bstNode<int, long unsigned int>::tree_copy(bstNode<int, long unsigned int>*&)’
bstNode.h:83: note: candidates are: bstNode<Item, Key>* bstNode<Item, Key>::tree_copy(const bstNode<Item, Key>*&) [with Item = int, Key = long unsigned int]
The prototype is exactly the same as the function’s implementation, sans the bstNode:: so I’m not sure what’s going on. I’m using the g++ compiler. Any ideas? Much appreciated, thanks.
EDIT: I cut down on the code to try and highlight the problem.
The compiler (as in most cases) is right in rejecting the code. The problem is that there is no conversion from
T*&toconst T*&, so the existing function cannot be used.Why is that conversion not present?
The reason for that conversion not to be present is that it would break const-correctness. Consider this example:
Now, a possible solution, since you do not need to modify the pointer passed to the function is to add even more
consts to the signature:In doing so, you are blocking the code from changing the pointer, which is the problem in the example above. But, if you really think about it,
Why do you pass a reference to a pointer in the first place?
Pointers are cheap to copy, so passing them by
const&does not make much sense, and since you do not need the function to change the pointer that you are passing, passing by value will be both correct and potentially more efficient.