GSI

for_each 에 대해서...(이펙티브 STL 내용 발췌.. 243 페이지)

이 알고리즘은 범위 내의 데이터를 요약할 수 있는 또 하나의 알고리즘이면서 accumulate가 가진 이상한 제한도 받지 않습니다. for_each는 범위와 그 범위 내의 요소에 대해 호출할 함수(대개 함수 객체)를 받아 들이는데, 이 알고리즘에 넘겨지는 함수는 자신이 처리할 단 하나의 요소만을 받아들이며, for_each는 자신의 수행을 마칠 때 이 함수를 반환합니다(엄밀히 말하면 그 함수의 사본(copy) 입니다.  항목 38에서 더 자세히 공부하세요). 가장 중요한 포인트는 for_each에 넘겨지는 (그리고 반환되는) 함수는 부가적 효과를 가져도 된다는 것입니다.

부가적 효과에 대한 사항을 차지하고라도, for_each는 두 가지 면에서 accumulate와 다릅니다. 우선 accumulate라는 이름 자체에서 "범위를 요약한다"는 느낌이 강하게 풍겨집니다. for_each는 "범위 내의 모든 요소에 어떤 일을 한다"라는 냄새가 나죠. 물론 이 알고리즘들의 일차적인 목적이 그것이겠지만요. 어쨌든 for_each를 써서도 범위를 요약할 수 있습니다. 하지만 accumulate처럼 확실하지 않다는 것 뿐이죠.

두번째, accumulate는 우리가 원하는 요약 결과를 바로 반환하지만, for_each는 자신이 매게 변수로 받은 함수 객체를 반환하기 때문에 이 객체에서 요약 정보를 뽑아내야 합니다. C++ 업에 용어로 말하면 for_each에 넘기는 함수자 객체에다가 요약 정보를 얻어 낼 수 있는 멤버 함수를 추가해야 한다는 의미이지요.

.. 이상..

대부분 vector의 예를 보면 간단하게 아래와 같이 서술할 겁니다.

class CTest
{
public:
  CTest() {}
  ~CTest() {}

private:
  ... 내용...
};

void Test(CTest& e) { ... 내용... }

vector<CTest> m_vTest;

//배열의 정보를 사용해서 Test() 함수를 실행할려고 할때.

vector<CTest>::iterator iter;
for(iter = m_vTest.Begin(); iter != m_vTest.End(); iter++) {
  Test((*iter));
}

//이런 형태로 구성하게 되지요.
//하지만 for_each를 구성하면 한줄로 심플하게 구성됩니다.

std::for_each(m_vTest.Begin(), m_vTest.End(), &Test);

//이렇게 한줄로 요약이 되는군요.
//여기서 조금더 확장해서  Test() 함수에 템플릿을 연동하면
//비슷한 형태의 다른 타입의 vector로 선언된 변수들을 연동할수 있습니다.

template < class T >
void Test(T& e) { ... 내용 ... }
std::for_each(m_vTest.Begin(), m_vTest.End(), &Test);

//이렇게만 구성하면 컴파일 오류가 납니다.
//아래와 같이 구성하시면 됩니다.

std::for_each(m_vTest.Begin(), m_vTest.End(), &Test<CTest>);

위의 코드는 오류가 있을지도 모릅니다. 제 나름대로 정리해본겁니다.
하지만 위의 코드가 더 다양한 방법으로 전환되기도 하더군요.
예를 들어서 CTest 클래스 내부에 Test() 함수를 넣고 그것을 for_each에 연동할 수 있더라구요.
Exceptional C++ Style 책에 보니 내용이 있더라구요.
아래와 같은 코드로 사용하면 되는듯 합니다.

std::for_each(m_vTest.Begin(), m_vTest.End(), std::mem_fun_ref( &CTest::Test));

이렇게 구성하시면 됩니다.
아 그리고 for_each는 Test가 반환되는 값이 있다면 앞쪽에 붙여서 받으면 되요.

Posted by gsi
: