다차원 배열 템플릿 클래스
글쓴이: jinserk / 작성시간: 목, 2009/12/03 - 10:50오전
struct exarray { enum ex_kind { DIM_ERROR, OUT_OF_RANGE }; ex_kind code_; std::string err_; exarray(ex_kind code) { code_ = code; switch (code) { case DIM_ERROR: err_ = "dimension error"; break; case OUT_OF_RANGE: err_ = "out of range"; break; default: err_ = "unknown error"; } } std::string& what(void) { return err_; } }; template <typename T> class array { private: bool is_con_; // container flag array<T>* con_; // container vector T* mem_; // value vector int dim_; // dimension int sz_; // size int pos_; // current position public: array() { is_con_ = false; con_ = NULL; mem_ = NULL; dim_ = 0; sz_ = 0; pos_ = 0; } array(int s1) { set(s1); } array(int s1, int s2) { set(s1, s2); } ~array() { clear(); } inline void set(int s1) { is_con_ = false; con_ = NULL; mem_ = new T[s1]; dim_ = 1; sz_ = s1; pos_ = 0; } inline void set(int s1, int s2) { is_con_ = true; con_ = new array<T> [s1]; mem_ = NULL; dim_ = 2; sz_ = s1; pos_ = 0; for (int i = 0; i < s1; i++) con_[i].set(s2); } inline void clear(void) { if (is_con_) { for (int i = 0; i < sz_; i++) { con_[i].clear(); delete [] con_; is_con_ = false; con_ = NULL; dim_ = 0; sz_ = 0; pos_ = 0; } } else { delete [] mem_; is_con_ = false; mem_ = NULL; dim_ = 0; sz_ = 0; pos_ = 0; } } inline void raise_error(exarray::ex_kind err) { exarray e(err); std::cerr << e.what() << std::endl; throw e; } inline array<T>& operator[] (int i) { if (dim_ < 2) raise_error(exarray::DIM_ERROR); if (i > sz_) raise_error(exarray::OUT_OF_RANGE); return con_[i]; } inline T& operator() (int i1) { if (dim_ > 1) raise_error(exarray::DIM_ERROR); if (i1 >= sz_) raise_error(exarray::OUT_OF_RANGE); return mem_[i1]; } inline T& operator() (int i1, int i2) { if (i1 >= sz_) raise_error(exarray::OUT_OF_RANGE); return con_[i1](i2); } inline void reset_pos(void) { pos_ = 0; } inline int push(T& e) { int over = 0; if (is_con_) { over = con_[pos_].push(e); if (over) { pos_++; } return 0; } mem_[pos_++] = e; if (pos_ == sz_) { pos_ = 0; return 1; } return 0; } inline int size(void) { return sz_; } inline int is_container(void) { return is_con_; } }; // function templates template <typename T> inline array<T>& operator+= (array<T>& ar, T rhs) { ar.push(rhs); return ar; } template <typename T> inline array<T>& operator, (array<T>& ar, T rhs) { ar.push(rhs); return ar; } template <typename T, typename CharT, class Traits> inline std::basic_ostream<CharT, Traits>& operator<< (std::basic_ostream<CharT, Traits>& ostr, array<T>& ar) { std::basic_ostringstream<CharT, Traits> os; os.flags(ostr.flags()); os.imbue(ostr.getloc()); os.precision(ostr.precision()); if (ar.is_container()) for (int i = 0; i < ar.size(); i++) os << ar[i] << std::endl; else for (int i = 0; i < ar.size(); i++) os << ar(i) << ' '; return ostr << os.str(); }
http://kldp.org/node/108905 에서 pensaku 님이 주신 힌트를 갖고
위와 같이 다차원 배열 클래스를 만들었습니다.
일단 2차원까지는 동작은 그럭저럭 하는 듯 합니다.
그런데 한가지.. array A 의 특정 부분을 참조할때
지금은 원소 조회할때는 () 를 쓰고 상위 container 조회는 [] 를 쓰는데
이를 통일하고 싶습니다.
예를 들어 A(1,2) 조회를 A[1][2] 와 같이 하고 싶은거지요.
근데 이렇게 하려면 위와 같은 구조에서는 operator[] 의 리턴값이 is_con_ 값에 따라
T& 가 되거나 혹은 array<T>&
가 되어야 하는데.. 이게 안되네요.
뭔가 좋은 방법이 없을까요? 굳이 operator [] 를 안쓰고 operator() 를 써도 좋습니다.
단지 mem_ 참조시 ()를 쓰고 con_ 참조시 [] 를 따로 쓰는 구조를 통일하고 싶은거지요.
마땅히 방법이 떠오르지 않아 문의 드립니다.
원 글에 쓰레드를 붙일까 하다가 질문 내용이 약간 다른 거라 새글로 작성합니다.
Forums:
댓글 달기