#include <iostream>
#include <string>
#include <vector>
#include <iterator>

namespace internal
{
    class PREORDER {};
    class POSTORDER {};

    // ----------------------------------------------------------------------------------
    template<typename P, typename IT>
    class my_iterator;


    template<typename P>
    class my_iterator<P, PREORDER>
    : public std::iterator<std::forward_iterator_tag, P>
    {
    private:
        int index;
    protected:
    public:
        my_iterator () { index = 0; }

        my_iterator& operator++ () {
            std::cout << "Preorder visit of GenericTree of nodes containing int values." << std::endl;
            return (*this);
        }
    };
    // ----------------------------------------------------------------------------------
    template<typename P>
    class my_iterator<P, POSTORDER>
    : public std::iterator<std::forward_iterator_tag, P>
    {
    private:
        int index;
    protected:
    public:
        my_iterator () { index = 0; }

        my_iterator& operator++ () {
            std::cout << "Postorder visit of GenericTree of nodes containing int values." << std::endl;
            return (*this);
        }
    };

}

template<typename P> class GenericTree
{
public:
    template <typename IT>
    using my_iterator = internal::my_iterator<P, IT>;
    using PREORDER = internal::PREORDER;
    using POSTORDER = internal::POSTORDER;

    std::vector<P> data;
    GenericTree () {}
    ~GenericTree () {}
};



int main ()
{
    GenericTree<int> c_int;
    GenericTree<int>::my_iterator<GenericTree<int>::PREORDER> iterator_int;

    ++iterator_int;

    GenericTree<std::string> c_string;
    GenericTree<std::string>::my_iterator<GenericTree<std::string>::POSTORDER> iterator_str;

    ++iterator_str;
    return 0;
}
