I am working on a binary search tree, where the order matters.
If a node/ nodes get modified, the tree need update to keep the order right.
What I want to do is overload the visiting methods, such as preOrderTraversal
; so that it can distinguish whether the function will modify the nodes or not.
void preOrderTraversal(std::function<void(Type)> visit); // read only visit
and
void preOrderTraversal(std::function<void(Type &)> visit); // write visit, update needed afterwards
if the std::function
passed in is value parameter typed, means a read only visit, so no need to update the tree; if std::function
is reference typed, the tree will be modified, hence update
method need to be called.
I know that I can mark preOrderTraversal
method as const
and non const
overload. However, would it be clear if we know the function pass in can change tree node or not, and overload them.
template<typename Type>
class BinaryTree {
public:
struct Node {
Type data;
Node* left{ nullptr };
Node* right{ nullptr };
Node(Type && value) : data{ std::move(value) } { }
Node() = delete;
};
// ... omit unrealated parts ...
// head, left leaf, right leaf
// value type, tree will not be modified
void preOrderTraversal(std::function<void(Type)> visit) {
std::cout << "void preOrderTraversal(std::function<void(Type)>)" << std::endl;
preorder_utility(visit);
}
// reference type, tree will be modified; so the tree need update order of nodes.
void preOrderTraversal(std::function<void(Type&)> visit) {
std::cout << "void preOrderTraversal(std::function<void(Type&)>)" << std::endl;
preorder_utility(visit);
update(); // update function to keep the tree in binary search tree order.
}
private:
template <typename Function>
void preorder_utility(Function visit) {
if( nullptr == root ) return;
std::stack<Node*> stack;
stack.push(root);
while( !stack.empty() ) {
auto node = stack.top();
stack.pop();
visit(node->data);
if( node->right ) {
stack.push(node->right);
}
if( node->left ) {
stack.push(node->left);
}
}
}
Node* root{nullptr};
};
So that we can have visit function can modify the tree or not.
// just as an example, readonly can not change the tree,
// while write may change the tree
void readonly(double value) {
// value inside tree will not change
value += 10.0;
std::cout << value << std::endl;
}
void write(double & value) {
// value inside tree will change
value += 10.0;
std::cout << value << std::endl;
}
so
int main() {
BinaryTree<double> btree;
// ... working on the tree..., push, pop, etc.
btree.preOrderTraversal(readonly);
btree.preOrderTraversal(write);
}
[update]
It looks like if I make readonly
take rvalue-reference, the code will compile and work.
// this will call void preOrderTraversal(std::function<void(Type)> visit)
// hence no update method will be called.
void readonly(double && value) {
// value inside tree will not change
value += 10.0;
std::cout << value << std::endl;
}