STL 의 bind1st 와 bind2nd 함수의 의미 및 사용법을 살펴 보자.
bind1st 와 bind2nd 함수는 모두 binary function object 를 unary function object 로 바꾸는 역할을 한다. 이 때, 그 binary function 의 첫 번째 혹은 두 번째 인자를 지정하느냐에 따라 bind1st 혹은 bind2nd 함수를 사용하게 되는 것이다. 여러 가지 이해해야 할 개념이 있는데 차근차근 살펴 보자.
unary function: 인자로 한 개의 값만을 받는 함수.
binary function: 인자로 두 개의 값을 받는 함수.
unary function 의 예로는 NOT 연산자 같은 것이 있다. 또는 집합에서의 여집합 연산자 역시 unary function 이라 할 수 있다. binary function 의 경우 수학에서 흔히 보던 많은 것들이 이에 해당하는데, 사칙연산, 부등호 등이 이에 해당한다. 즉, + 연산은 '두 개'의 값이 있어야 계산되는 연산인 것이다.
그럼 왜 binary function 을 unary 로 바꾸어야 하는가? 그것은, STL 의 어떤 함수들은 unary function 을 인자로 받기 때문이다. 예를 들면 count_if 같은 함수. 세 번째 인자로 받은 함수 객체에 대하여 참을 반환하는 element 의 수를 세는 함수가 count_if 이다. 이 세 번째 인자가 unary function (predicate) 을 받는다. 만약 '~보다 작은 수'를 세고 싶다면 이 '작다'는 연산자를 unary 로 만들어서 count_if 에 넘겨 줘야 한다.
count_if(values.begin(), values.end(), std::bind1st(std::less<double>(), threshold));
와 같은 식이다. 약간 복잡해 보이는 부분은 bind1st 와 less, threshold 가 어떤 식으로 작동하는가, 인데, 다음과 같다. std::less 나 std::greater 같은 연산자는 곧 < 과 > 연산자이고, 이 연산자들은 두 개의 값을 입력으로 받아 왼쪽에 있는 값을 기준으로 해서 결과를 반환해 준다. 즉, (+, 3, -1) 을 3 + (-1), 을 의미하는 것처럼 표기해 보자면, (< , 9, 1 ) 은 9 < 1 을 의미하는 것이고, 이 때 첫 번째 인자인 9 를 기준으로 9 < 1 을 판단해서 결과값(거짓)을 반환하는 것이다. 즉, std::less 나 std::greater 같은 연산자들은 모두 이항연산자인 것이다. 이 때, 위의 코드같은 경우 bind1st 를 사용했으므로, ( < , threshold, v ), 가 되고, threshold < v , 이 때 v 는 values 의 요소들, 로 연산이 이루어지게 되는 것이다. 간단히 말하면, 1
1) bind1st(less<double>(), threshold) 는 ( < , threshold, v) for v in values ==> threshold < v for v in values,
2) bind2nd(less<double>(), threshold) 는 ( < , v, threshold ) for v in values ==> v < threshold for v in values,
3) bind1st(greater<double>(), threshold) 는 ( > , threshold, v ) for v in values ==> threshold > v for v in values,
4) bind2nd(greater<double>(), threshold) 는 ( > , v, threshold ) for v in values ==> v > threshold for v in values,
가 되는 것이다. 그러므로 1) 은 threshold 보다 큰 요소의 개수를 찾을 것이고 (less 를 사용했지만), 4) 의 경우에는 greater 를 사용했지만 2nd 로 묶었기 때문에 threshold 보다 작은 요소의 개수를 찾을 것이다. 둘 모두 잘못된 것은 아니고, 단지 자신의 상황에 맞게 함수를 사용하면 된다.
실제로 위 함수들은 binder1st 나 binder2nd class 를 이용해서 만든 함수들이다. 이런 함수가 상속/template 을 멋지게 사용한 예라 할 수 있지, ㅋ, 매우 짧긴 해도.
- 이런 식의 규칙들은 중학교 수학에 나오는 듯 하다. 즉, 기호나 표기의 정의를 새롭게 해보는 것. 이런 게 수학에선 매우 중요한데 그 중요성이 자주 간과되는 듯 싶어 안타깝다. [본문으로]
'컴퓨터 > C++_STL' 카테고리의 다른 글
포인터, 참조, 값 형식에 관한 개인적 관례 (0) | 2014.05.09 |
---|---|
포인터에 대한 짤막한 이야기 (2) | 2014.04.02 |
파일 읽기 편하게 하기 (0) | 2013.05.01 |
const pointer (0) | 2011.11.23 |
isnan과 isinf (0) | 2010.12.06 |