1

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;
}
user9245717
  • 11
  • 1
  • 2

0 Answers0