#include <iostream>
using namespace std;
template<typename T> class slist
{
        struct Node
        {
               T         data;
               Node* next;
               Node( T d, Node* n ) : data(d), next(n) {}
        };
        Node* head;
public:
        slist() : head(0)      {}
        void push_front( T a ) { head = new Node( a, head ); }
        // list의각요소를접근하기위해스마트포인터를넣는다.
        // 내포로만들거나외부에(그리고내부에typedef로선언) 만들수있다.
        class iterator
        {
               Node* current;
        public:
               typedef T value_type;
               iterator( Node* init = 0 ) : current( init ) {}
               iterator& operator++()
               {
                       current = current->next;
                       return *this;
               }
               T& operator* ()
               {
                       return current->data;
               }
               bool operator !=( const iterator& i )
               {
                       return (current != i.current);
               }
        };
        //-------------------------------------------------------
        // 이제slist의처음과past the end iterator를리턴하는함수를제공한다.
        iterator begin() { return iterator(head); }
        iterator end() { return iterator( 0 ); }
};
/*
// 주어진구간의합을출력하는알고리즘을만들고싶다.
// 컴파일러에의한타입추론(type ??), 타입을알지못하므로컴파일러에게맡긴다??
// 단점: 리턴값을갖지못한다. 타입을모르므로?? void!!
template<typename T, typename T2> void sum_imp( T first, T last, T2 init )
{
        T2 s = init;
        while ( ++first != last )
        {
               s = s + *first;
        }
        cout << s << endl;
}
template<typename T> void sum( T first, T last )
{
        sum_imp( first, last, *first );
}
*/
// 버전2. 주어진구간의합을리턴하는함수를만들어보자.
// 모든반복자는자신과연관된type을typedef로가지고있다.( value_type으로꺼내면된다. )
// 간접층을만들어type문제를해결한다. (int, int), 반복자특성클래스.
template<typename T> struct xiterator_traits
{
        typedef typename T::value_type value_type;
};
// template 부분전문화( 포인터로되어있는것)
template<typename T> struct xiterator_traits<T*>
{
        typedef T value_type;
};
template<typename T>
typename xiterator_traits<T>::value_type sum( T first, T last )
{
        //typename T::value_type s = *first;
        // 어떠한타입이올지모르므로0을대입해서는안된다.
        typename xiterator_traits<T>::value_type s = *first;
        while ( ++first != last )
        {
               s = s + *first;
        }
        return s;
}
void main()
{
        int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        int n2 = sum( x, x+10 );
        slist<int> s;
        s.push_front( 10 );
        s.push_front( 20 );
        s.push_front( 30 );
        s.push_front( 40 );
        //slist안에있는모든요소의합을구하고싶다.
        int k = sum( s.begin(), s.end() );
        cout << k << endl;
}
////////////////////////////////////////////////////////////////////
// iterator_category 의 구현
{
        typedef typename T::value_type value_type;
        typedef typename T::iterator_category iterator_category;
};
// template 부분전문화( 포인터로되어있는것)
template<typename T> struct xiterator_traits<T*>
{
        typedef T value_type;
        typedef random_access_iterator_tag   iterator_category;
};
//임의접근일경우
template<typename T> void xadvance(T& p, int n ,random_access_iterator_tag)
{ 
        p += n;
}
template<typename T>
void xadvance( T& p, int n )
{
        xadvance( p, n, xiterator_traits<T>::iterator_category() );
}
void main()
{
        int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        int *p = x;
xadvance( p, 3 ); // p의반복자를3만큼전진해야한다. p+n 처리를하자.
        cout << *p << endl;    // 4이나와야한다.
}
