I'm trying to replace the use of raw pointers with smart pointers in my C++ code. The following bit is from my first attempt at a self-balancing binary tree, though there is nothing self-balancing at the moment. I am worried about some fundamental problems regarding the use of unique pointers. 

    template <typename K, typename D>
    class rbtree {
        struct rbnode;
        typedef std::unique_ptr<rbnode> node_ptr;
        node_ptr root_;
    
        struct rbnode {
            node_ptr left, right;
            rbnode *parent;
            enum { Red, Black } color;
            D data;
            K key;
            rbnode(): 
                left(nullptr), right(nullptr), parent(nullptr), 
                color(Red), data(0), key(0) {}
            rbnode(K k, D d): 
                left(nullptr), right(nullptr), parent(nullptr), 
                color(Red), data(d), key(k) {}
            rbnode(K k, D d, rbnode *p): 
                left(nullptr), right(nullptr), parent(p), 
                color(Red), data(d), key(k) {}
        };
    
        node_ptr insert_(node_ptr& node, node_ptr& parent, K& key, D& data);
        public:
            
            bool insert(K& key, D& data);
            void dfs(std::function<void (K& key, D& data)> visitor);
    };
    
    template <typename K, typename D>
    void rbtree<K, D>::dfs(std::function<void (K& key, D& data)> visitor) {
    }
    
    template <typename K, typename D>
    typename rbtree<K, D>::node_ptr rbtree<K, D>::insert_(
            node_ptr& node, node_ptr& parent, K& key, D& data) {
        if (node == 0) { node = node_ptr(new rbnode(key, data, parent.get())); }
        if (key == node->key) { throw "Key exists!"; }
        if (key < node->key) {
            node->left = std::move(insert_(node->left, node, key, data));
        } else {
            node->right = std::move(insert_(node->right, node, key, data));
        }
        return std::move(node);
    }
    
    template <typename K, typename D>
    bool rbtree<K, D>::insert(K& key, D& data) {
        root_ = std::move(insert_(root_, root_, key, data));
        root_->color = rbnode::Black;
        return true;
    }