순차형(sequential) 컬렉션
typedef std::list<OBJECT*> OBJECTS;
OBJECTS objects;
...
for (OBJECTS::iterator itr(objects.begin()); itr != object.end(); )
{
OBJECT* object = *itr;
if (should_delete(object))
{
itr = objects.erase(itr);
delete object;
}
else itr++;
}
OBJECTS objects;
...
for (OBJECTS::iterator itr(objects.begin()); itr != object.end(); )
{
OBJECT* object = *itr;
if (should_delete(object))
{
itr = objects.erase(itr);
delete object;
}
else itr++;
}
연관형(associative) 컬렉션
typedef std::map<int, OBJECT*> OBJECTS;
OBJECTS objects;
...
for (OBJECTS::iterator itr(objects.begin()); itr != object.end(); )
{
OBJECT* object = itr->second;
if (should_delete(object))
{
objects.erase(itr++);
delete object;
}
else itr++;
}
OBJECTS objects;
...
for (OBJECTS::iterator itr(objects.begin()); itr != object.end(); )
{
OBJECT* object = itr->second;
if (should_delete(object))
{
objects.erase(itr++);
delete object;
}
else itr++;
}
문제는 둘이 비슷비슷해서 자꾸 착각한다는 것. 컨테이너가 어떤 것이냐와는 상관없이 아이템을 삭제하고 싶었다. 더불어 컨테이너에 들어있는 것이 일반(?) 변수인지 포인터 변수인지도 신경쓰고 싶지 않았다. 뜻이 있는 곳에 길이 있는 법.
struct YES {};
struct NO {};
template <typename T>
struct is_ptr
{
enum { result = false };
typedef NO Result;
};
template <typename T>
struct is_ptr<T*>
{
enum { result = true };
typedef YES Result;
};
template <typename T>
struct is_ptr<T* const>
{
enum { result = true };
typedef YES Result;
};
template <typename T>
struct is_ptr<T* volatile>
{
enum { result = true };
typedef YES Result;
};
template <typename T>
struct is_ptr<T* const volatile>
{
enum { result = true };
typedef YES Result;
};
template <typename T>
class is_pair
{
private:
template <typename U>
struct is_pair_imp
{
enum { value = false };
typedef NO Result;
};
template <typename U, typename V>
struct is_pair_imp < std::pair<U, V> >
{
enum { value = true };
typedef YES Result;
};
public:
enum { value = is_pair_imp<T>::value };
typedef typename is_pair_imp<T>::Result Result;
};
template <typename IS_POINTER>
struct do_delete {};
template <>
struct do_delete<YES>
{
template <typename U>
void operator()(U param) { delete param; }
};
template <>
struct do_delete<NO>
{
template <typename U>
void operator()(U param) {}
};
template <typename IS_ASSOCIATION>
struct delete_if_imp {};
template <>
struct delete_if_imp<YES>
{
template <typename C, typename P>
void operator()(C& con, P comp)
{
do_delete< is_ptr<C::value_type::second_type>::Result > doDelete;
for (C::iterator itr(con.begin()); itr != con.end();)
{
if (comp(itr->second))
{
doDelete(itr->second);
con.erase(itr++);
}
else ++itr;
}
}
};
template <>
struct delete_if_imp<NO>
{
template <typename C, typename P>
void operator()(C& con, P comp)
{
do_delete< is_ptr<C::value_type>::Result > doDelete;
for (C::iterator itr(con.begin()); itr != con.end();)
{
if (comp(*itr))
{
doDelete(*itr);
itr = con.erase(itr);
}
else ++itr;
}
}
};
template <typename C, typename P>
inline void delete_if(C& con, P comp)
{
delete_if_imp< is_pair<C::value_type>::Result > imp;
imp(con, comp);
}
struct NO {};
template <typename T>
struct is_ptr
{
enum { result = false };
typedef NO Result;
};
template <typename T>
struct is_ptr<T*>
{
enum { result = true };
typedef YES Result;
};
template <typename T>
struct is_ptr<T* const>
{
enum { result = true };
typedef YES Result;
};
template <typename T>
struct is_ptr<T* volatile>
{
enum { result = true };
typedef YES Result;
};
template <typename T>
struct is_ptr<T* const volatile>
{
enum { result = true };
typedef YES Result;
};
template <typename T>
class is_pair
{
private:
template <typename U>
struct is_pair_imp
{
enum { value = false };
typedef NO Result;
};
template <typename U, typename V>
struct is_pair_imp < std::pair<U, V> >
{
enum { value = true };
typedef YES Result;
};
public:
enum { value = is_pair_imp<T>::value };
typedef typename is_pair_imp<T>::Result Result;
};
template <typename IS_POINTER>
struct do_delete {};
template <>
struct do_delete<YES>
{
template <typename U>
void operator()(U param) { delete param; }
};
template <>
struct do_delete<NO>
{
template <typename U>
void operator()(U param) {}
};
template <typename IS_ASSOCIATION>
struct delete_if_imp {};
template <>
struct delete_if_imp<YES>
{
template <typename C, typename P>
void operator()(C& con, P comp)
{
do_delete< is_ptr<C::value_type::second_type>::Result > doDelete;
for (C::iterator itr(con.begin()); itr != con.end();)
{
if (comp(itr->second))
{
doDelete(itr->second);
con.erase(itr++);
}
else ++itr;
}
}
};
template <>
struct delete_if_imp<NO>
{
template <typename C, typename P>
void operator()(C& con, P comp)
{
do_delete< is_ptr<C::value_type>::Result > doDelete;
for (C::iterator itr(con.begin()); itr != con.end();)
{
if (comp(*itr))
{
doDelete(*itr);
itr = con.erase(itr);
}
else ++itr;
}
}
};
template <typename C, typename P>
inline void delete_if(C& con, P comp)
{
delete_if_imp< is_pair<C::value_type>::Result > imp;
imp(con, comp);
}
하는 일에 비해 코드가 꽤 길어졌다. 뭐 어쨌든 최종 결과물인 delete_if 함수를 이용하면 컨테이너의 종류와 상관없이 아이템을 삭제할 수 있다.
class test
{
private:
int myValue;
public:
test(int value = 0) : myValue(value) {}
~test()
{
//std::cout << myValue << " dying" << std::endl;
}
};
struct COMPARE_TEST
{
bool operator()(test* t) { return t->myValue < 2; }
bool operator()(test& t) { return t.myValue < 2; }
};
int main()
{
std::map<int, test*> myMap;
std::map<int, test> myMap2;
std::vector<test*> myVector;
myMap[0] = new test(0);
myMap[1] = new test(1);
myMap[2] = new test(2);
myMap[3] = new test(3);
myMap2[0] = test(0);
myMap2[1] = test(1);
myMap2[2] = test(2);
myMap2[3] = test(3);
myVector.push_back(new test(0));
myVector.push_back(new test(1));
myVector.push_back(new test(2));
myVector.push_back(new test(3));
std::cout << ">> MAP BEFORE: " << myMap.size() << std::endl;
delete_if(myMap, COMPARE_TEST());
std::cout << ">> MAP AFTER: " << myMap.size() << std::endl;
std::cout << ">> MAP2 BEFORE: " << myMap2.size() << std::endl;
delete_if(myMap2, COMPARE_TEST());
std::cout << ">> MAP2 AFTER: " << myMap2.size() << std::endl;
std::cout << ">> VECTOR BEFORE: " << myVector.size() << std::endl;
delete_if(myVector, COMPARE_TEST());
std::cout << ">> VECTOR AFTER: " << myVector.size() << std::endl;
return 0;
}
{
private:
int myValue;
public:
test(int value = 0) : myValue(value) {}
~test()
{
//std::cout << myValue << " dying" << std::endl;
}
};
struct COMPARE_TEST
{
bool operator()(test* t) { return t->myValue < 2; }
bool operator()(test& t) { return t.myValue < 2; }
};
int main()
{
std::map<int, test*> myMap;
std::map<int, test> myMap2;
std::vector<test*> myVector;
myMap[0] = new test(0);
myMap[1] = new test(1);
myMap[2] = new test(2);
myMap[3] = new test(3);
myMap2[0] = test(0);
myMap2[1] = test(1);
myMap2[2] = test(2);
myMap2[3] = test(3);
myVector.push_back(new test(0));
myVector.push_back(new test(1));
myVector.push_back(new test(2));
myVector.push_back(new test(3));
std::cout << ">> MAP BEFORE: " << myMap.size() << std::endl;
delete_if(myMap, COMPARE_TEST());
std::cout << ">> MAP AFTER: " << myMap.size() << std::endl;
std::cout << ">> MAP2 BEFORE: " << myMap2.size() << std::endl;
delete_if(myMap2, COMPARE_TEST());
std::cout << ">> MAP2 AFTER: " << myMap2.size() << std::endl;
std::cout << ">> VECTOR BEFORE: " << myVector.size() << std::endl;
delete_if(myVector, COMPARE_TEST());
std::cout << ">> VECTOR AFTER: " << myVector.size() << std::endl;
return 0;
}

글
댓글을 달아 주세요
댓글 RSS 주소 : http://serious-code.net/tc/rss/comment/5댓글 ATOM 주소 : http://serious-code.net/tc/atom/comment/5