다차원 배열 템플릿 클래스
글쓴이: 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:


댓글 달기