프로그래밍/cpp

[C++11]바인더, std::bind, std::function, std::spaceholder::_1, bind1st, bind2st

콘파냐 2015. 4. 25. 21:22
반응형

바인더는 STL  함수 어댑터다. std::bind는 C++11에서 표준으로 제공하는 바인더로 기존의 bind1st, bind2st 보다 다양한 활용을 할 수 있는 어댑터다. 기존의 bind1st, bind2st는 두 개의 파라미터를 갖는 객체함수의 파라미터를 고정시켜 주는데, bind1st는 첫 번째 파라미터를 bind2st는 두 번째 파라미터에 고정값을 준다.


일반적으로 bind1st와 bind2st는 STL 이항 함수자(함수객체)를 단항으로 바꾸는데 쓰인다.

다시말해 들어 비교를 하는 STL 함수 객체(함수자) equal_to, not_equal_to, less, greater,.....등을 단항함수로 만든다.


위 코드를 분석해보자.

bind1st는 이항함수자를 단항함수자로 만들어 반환한다. binder1st는 단항함수자 클래스다. bind1st 바인더는 대상의 1번째 파라미터를 1로 고정시킨다. (bind2st 바인더는 2번재 파라미터를 고정시킨다.)


함수자(STL의 객체함수)뿐 아니라 사용자가 만든 이항함수를 위와같이 사용하고 싶다면?

사실 항이 2개로 고정되어 있어서 그렇게 실용적이지 않고 사용에 제한이 있다. 기존 표준에 항이 두개인 경우만 적용했던 걸 보면 STL 이항 함수자를 단항으로 바꾸어 쓸 목적으로 설계한 듯 싶다.

아무튼 다음과 같이 사용하면 된다.


객체함수를 정의할 때 7~9 만 맞춰서 넣어주면 된다.

()연산자 오버로딩은 const로 설정한다.

대략 감은 오지만 내부 설정은 꽤 복잡하다. 대강 이해하고 넘어가는 게 좋다. 우리에게는 C++11에서 표준이된 std::bind가 있다.


std::bind

이 녀석은 C++11에서 표준이 된 함수 어댑터이다. 위 bind1st, bind2st,에 비교불가로 매우 강력하다. 단 이 녀석은 같이 붙어 다니는 녀석들이 있다.

std::function //타입

std::placeholders::_1  //객체

std::placeholders::_2

...

...



먼저 bind의 사용법을 간단히 살펴보면,

인자 3개를 가지는 함수를 f(3)을 보면 알 수 있듯이 인자 1개를 가지는 함수로 바꾸었다. bind의 첫 번째 인자는 원본(바꾸고자하는) 함수명을 써주고, 두 번째 인자는 원본 함수의 첫 번째 인자, 세 번째 인자는 원본 함수의 두 번째 인자.....와 매칭된다. 여기서 첫 번째 인자에 placeholders::_1을 사용하고 2,3 번째 인자에는 실제 값을 넣었다. 실제 값을 넣으면 그 인수는 항상 그 값이 되기 때문에, 파라미터에서 제외된다. 결국 placeholders::_1객체 부분만 남았다. std::placeholders::_1 객체는 원본 함수의 1번째 인자를 뜻한다.


실행결과는

3 1 str 


그럼 좀 더 실용적인 예를 들어보자.


1 함수 포인터를 파라미터로 받는 함수를 만들어보자.


함수 포인터를 모른다면.


2014/01/02 - [프로그래밍/c++] - 함수포인터(1)


func함수는 3번째 인자로 int인수 두 개 가지고 반환값이 int인 함수를 받는다. add 함수는 위 조건에 맞고 위 결과는 3이 나온다.


2. 조금 변경하여 add 함수를 x 함수로 바꾸어 보았다. 인자가 3개이므로 func 함수의 인자로 적합하지 않다. 아래 코드는 에러가 난다.




3. bind를 사용하여 3번째 인자를 고정값으로 만든후 인자값을 2개를 갖는 새로운 함수를 만든다.



제대로 동작할까?

그렇지 않다. f의 타입이 함수 포인터 타입이 아니다. 그래서 이 대입은 에러를 일으킨다.


여기선 함수포인터 대신 std::function 을 사용해야 한다. 사용법은 함수 포인터와 유사하다.



function<반환값(인수1,인수2,..)>

bind가 리턴하는 형태는 매우 복잡하다. auto 키워드를 사용하였고, std::function<....> 는 함수포인터, 함수객체,bind 리턴형, 람다함수 함수 등을 받을 수 있다.

사실상 모든 함수형태를 다 받을 수 있다.

반응형