Binary Search Tree implementation using smart pointers I have implemented below code for binary search tree implementation using shared pointer. At present, I have considered only integers. It supports insertion and deletion of values. Also, a print method is implemented for inorder traversal.

Please review and provide your suggestions.

class Bst {
    struct node {
        int val;
        shared_ptr&lt;node&gt; left, right;
        node(int v) : val(v), left(nullptr), right(nullptr){}           
    };
    shared_ptr&lt;node&gt; root;
    shared_ptr&lt;node&gt; _insert(shared_ptr&lt;node&gt; curr, int val);
    shared_ptr&lt;node&gt; _del(shared_ptr&lt;node&gt; curr, int val);
    shared_ptr&lt;node&gt; findmin(shared_ptr&lt;node&gt; curr);
    void _print(shared_ptr&lt;node&gt; curr);

public:
    void insert(int val) { root = _insert(root, val); }
    void del(int val) { root = _del(root, val); }
    void print() { _print(root); cout &lt;&lt; '\n'; }
};

shared_ptr&lt;Bst::node&gt; Bst::_insert(shared_ptr&lt;node&gt; curr, int val)
{
    if (curr == nullptr)
        return make_shared&lt;node&gt;(val);

    if (val &lt; curr-&gt;val)
        curr-&gt;left = _insert(curr-&gt;left, val);
    else
        curr-&gt;right = _insert(curr-&gt;right, val);

    return curr;
}
shared_ptr&lt;Bst::node&gt; Bst::findmin(shared_ptr&lt;node&gt; curr)
{
    while (curr-&gt;left)
        curr = curr-&gt;left;
    return curr;
}
shared_ptr&lt;Bst::node&gt; Bst::_del(shared_ptr&lt;node&gt; curr, int val)
{
    if (val &lt; curr-&gt;val)
        curr-&gt;left = _del(curr-&gt;left, val);
    else if (val &gt; curr-&gt;val)
        curr-&gt;right = _del(curr-&gt;right, val);
    else {
        if (curr-&gt;right == nullptr)
            return curr-&gt;left;
        if (curr-&gt;left == nullptr)
            return curr-&gt;right;
        shared_ptr&lt;node&gt; temp = findmin(curr-&gt;right);
        curr-&gt;val = temp-&gt;val;
        curr-&gt;right = _del(curr-&gt;right, curr-&gt;val);
    }
    return curr;
}
void Bst::_print(shared_ptr&lt;node&gt; curr)
{
    if (curr == nullptr)
        return;
    _print(curr-&gt;left);
    cout &lt;&lt; curr-&gt;val &lt;&lt; " ";
    _print(curr-&gt;right);
}
please do not using namespace std;
why has Bst::findmin no prefix _?
why do you use std::shared_ptr&lt;&gt; at all? std::shared_ptr is ment to represent shared ownership. This makes no sense for tree nodes, you're not going to have two trees with the same nodes. std::unique_ptr&lt;&gt; is a better candidate.
it is generally good to separate the data structure from its serialization. Make print a separate function and also handle the member printing outside of the class. 




Edit
As you had trouble getting the unique_ptr running, here's what works for me.

Modify the node to use unique_ptr:

struct node
{
    int val;
    std::unique_ptr&lt;node&gt; left;
    std::unique_ptr&lt;node&gt; right;

    // c'tor left out
};


Also, use a unique_ptr for root. You'll receive heavy compiler complaints, 
because a unique_ptr cannot be simply copied (one of the instances must go invalid, as it's unique). I suggest altering the private functions:

void _insert(std::unique_ptr&lt;node&gt;&amp; curr, int val);
void _del(std::unique_ptr&lt;node&gt;&amp; curr, int val);


Sample implementation for _insert:

void Bst::_insert(std::unique_ptr&lt;node&gt;&amp; curr, int val)
{
    if (!curr)
    {
       curr = std::make_unique&lt;node&gt;(val);
       return;
    }

    if (val &lt; curr-&gt;val)
    {
        _insert(curr-&gt;left, val);
    }
    else
    {
        _insert(curr-&gt;right, val);
    }
}


Your public insert method would be something like:

void insert(int val)
{ 
    _insert(root, val);
}


Also: add a find function to see if an element is in the tree. Use the find function to write some simple tests. You may rename del to erase to be closer at the standard naming. 



Edit 2 Separate output from data storage:

A friend function is relatively inflexible, as you cannot easily exchange the printing algorithm. You may implement iterators (hard) or provide a traverse function. I'd go for the second approach, as you already have the algorithm in _print: rename print to traverse and pass it a function pointer, then replace the output to std::cout by a call to the function pointer. 


class Bst
{
...
    // traverse with function pointer
    void traverse(void (*func)(int));
};

int main()
{
    Bst b;
    // insert data ...    

    b.traverse([](auto v){ std::cout &lt;&lt; v &lt;&lt; " "; });
    std::cout &lt;&lt; "\n";
}