#include <iostream>

class bst_t
{
private:
	struct node_t
	{
		node_t * left;
		node_t * right;
		int value;
	};

	node_t * root_;

	static void insert_node(node_t * & node, int value)
	{
		auto current_pointer = &node;

		while (true)
		{
			auto & current = *current_pointer;

			if (current == nullptr)
			{
				current = new node_t{nullptr, nullptr, value};
				return;
			}

			if (value < current->value) current_pointer = &current->left;
			else if (current->value < value) current_pointer = &current->right;
			else return;
		}
	}

	template<typename Functor>
	static void iterate_node(node_t * node, Functor functor)
	{
		if (node == nullptr) return;

		iterate_node(node->left, functor);
		functor(node->value);
		iterate_node(node->right, functor);
	}

	static void delete_node(node_t * node)
	{
		if (node == nullptr) return;

		delete_node(node->left);
		delete_node(node->right);
		delete node;
	}

public:
	bst_t()
	:
		root_{nullptr}
	{}

	~bst_t()
	{
		delete_node(root_);
	}

	void insert(int value)
	{
		insert_node(root_, value);
	}

	template<typename Functor>
	void iterate(Functor functor)
	{
		iterate_node(root_, functor);
	}
};

int main()
{
	bst_t bst;
	bst.insert(10);
	bst.insert(20);
	bst.insert(5);
	bst.insert(15);
	bst.insert(30);

	bst.iterate([](int i)
	{
		std::cout << i << "\n";
	});
}