#include <iostream>
#include <string>
using namespace std;
// 모든 반복자가 가져야 하는 인터페이스를 설계한다. - 실제 C#에는 아래의 interface가 있다.
// C# 1.0 에서는 Object 최상위클래스로 받아서 타입캐스팅을 했지만..
// C# 2.0 에서는 Generic의 도입으로 반복자 인터페이스가 편리해졌다.
template<typename T> struct IEnumerator
{
virtual bool MoveNext() = 0;
virtual T GetObject() = 0;
virtual void Reset() = 0;
};
//-------------------------------------------------------
// 또한 반복자를 가질 수 있는 모든 컨테이너는 아래의 인터페이스를 제공해야 한다.
template<typename T> struct IEnumerable
{
virtual IEnumerator<T>* GetEnumerator() = 0;
};
//-------------------------------------------------------
// 열거가능한(반복자를가진) 클래스는 반드시 IEnumerable에서 파생되어야 한다.
template<typename T> class slist : public IEnumerable<T>
{
struct Node
{
T data;
Node* next;
Node( T a, Node* n ) : data(a), next(n) {}
};
Node* head;
public:
slist() : head(0) {}
void push_back( T a ) { head = new Node( a, head ); }
// slist에서 값을 얻기 위한 반복자
class SlistEnumerator : public IEnumerator<T>
{
Node* current;
Node* head;
public:
SlistEnumerator( Node* init = 0 )
: head(init), current(init) {}
bool MoveNext()
{
current = current->next;
return current != 0;
}
int GetObject() { return current->data; }
void Reset() { current = head; }
};
//--------------------------------------------------
// 반복자를 리턴하는 함수를 만든다.
IEnumerator<T>* GetEnumerator()
{
return new SlistEnumerator( head );
}
};
//------------------------------------------------------
// 주어진 반복자를 사용해서 모든 요소의 합을 구한다.
template<typename T> void Sum( IEnumerator<T>* p )
{
T s = T();
p->Reset();
do
{
s += p->GetObject();
} while ( p->MoveNext() );
cout << s << endl;
}
// 주어진 컨테이너의 모든 요소의 합을 구한다.
template<typename T> void Sum2( IEnumerable<T>& c )
{
IEnumerator<T>* p = c.GetEnumerator();
Sum( p );
}
int main()
{
slist<int> s;
s.push_back( 10 );
s.push_back( 20 );
s.push_back( 30 );
//IEnumerator<int>* p = s.GetEnumerator();
//Sum( p );
Sum2( s );
return 0;
}