1 minute read

STL 알고리즘 이름의 _if 접미사는 술어 함수(predicate)를 인자로 받는 것을 의미한다. 이 술어 함수를 알고리즘 안에서 호출해서 돌려받은 반환 값에 따라 동작을 수행할지 말지를 결정하게 된다. 예를 들면 count_if()는 술어 함수 호출결과가 true인 원소들의 개수를 세는 알고리즘이고 remove_if()는 술어 함수 호출 결과가 true인 원소들을 제거하는 알고리즘이다.

시퀀스(Sequences - vector, list, deque) 알고리즘 중에 _if 가 있을만한 알고리즘인데 없는 알고리즘이 있다. 가장 단순한 형태인 복사를 수행하는 copy() 알고리즘이 주인공인데, 정말 있을법한데 없는 알고리즘이다. Effective STL 항목 36에서 이 사실을 알게 됐는데, 혹시나 싶어서 TC++PL을 보니 이 책에도 copy_if() 에 대한 언급이 있었다. 표준 위원회가 STL 명세를 결정할 때 제거한 알고리즘이다. Where is copy_if (was: STL question: where is find_first_not_of?)에서 비야네 스트롭스트룹의 답변을 볼 수 있다.

copy_if 구현

template<class In, class Out, class Pred>
Out copy_if(In first, In last, Out res, Pred p)
{
    while (first != last) {
        if (p(*first))    *res++ = *first;
        ++first;
    }
    return res;
}

이렇게 TC++PL에 실린 것처럼 직접 구현할 수도 있고

template<class In, class Out, class Pred>
Out copy_if(In first, In last, Out res, Pred p)
{
    return std::remove_copy_if(first, last, res, not1(p));
}

remove_copy_if() 알고리즘과 not1() 단항 술어 함수 어댑터를 사용해서 구현할 수 있다. VS 2005에 딩컴웨어 STL이나 STLport 같이 많이 사용하는 STL 구현 코드에서는 디버그 옵션을 켜면 반복자(iterator) 범위 체크 등 여러 검사를 해주는데, 그런 안정장치들을 직접 삽입해 줄 게 아니면 위처럼 직접 구현하는 것보다 구현된 알고리즘과 어댑터를 사용해 구현하는 게 안정성이나 재활용 측면에서 낫다고 생각한다.

copy() 알고리즘 활용

std::copy(
    v.begin(),
    v.end(),
    std::ostream_iterator<int>(std::cout, " "));

참고로 copy() 는 시작과 끝을 가리키는 반복자를 인자로 받는 시퀀스 생성자가 있어서 시퀀스에서 시퀀스로 단순 복사용으로는 잘 쓰이지 않는데, 세 번째 인자로 출력 반복자를 받는 것을 이용하면 시퀀스 원소들을 콘솔에 출력하는 작업 같은 일을 간단하게 처리할 수 있다.

PS : TC++PL을 정독하지 않고 필요한 부분만 참고 하고 있는데, Effective STL 정리가 마무리되면 다른 C++ 책들은 미루고 TC++PL을 정독해야겠다. 모든 게 다 이 책 안에 있다.

참고