본문 바로가기
Programming/C++ & STL

함수 어댑터(function adaptor)

by 한 땀; 한 땀; 2021. 1. 16.

함수 어댑터 : 함수를  함수 객체로 변환해주는 역할을 한다.

 

#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>
using namespace std;


bool predfunc(int n) 
{
	return 30 <= n;
}

int main()
{
	vector<int> v = { 10,20,30,40,50 };

	cout << "30 이하 원소 개수 : " << count_if(v.begin(), v.end(), predfunc) << endl;
	cout << "30 초과 원소 개수 : " << count_if(v.begin(), v.end(), not1(predfunc)) << endl;

	return 0;
}

위 코드는 부정자 not1 을 사용하려 할 때 에러가 발생한다. not1 함수는 argumnet_type 형식 정의를 필요로 한다. 따라서 이를 함수 어댑터를 만들어 함수 객체로 변경해준다.

 

#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>
using namespace std;

template<typename Rtype,typename Atype>
class Pred : public unary_function<Atype,Rtype>
{
private:
	Rtype(*pf)(Atype);
public:
	Pred(Rtype(*_pf)(Atype)) :pf(_pf) {}

	Rtype operator()(Atype n) const
	{
		return pf(n);
	}
};

template<typename Rtype,typename Atype>
Pred<Rtype, Atype> Adapt(Rtype(*pf)(Atype))
{
	return Pred<Rtype, Atype>(pf);
}

bool predfunc(int n)
{
	return 30 <= n;
}
int main()
{
	vector<int> v = { 10,20,30,40,50 };
    
	cout << "30 이하 원소 개수 : " << count_if(v.begin(), v.end(), predfunc) << endl;
	cout << "30 초과 원소 개수 : " << count_if(v.begin(), v.end(), not1(Adapt(predfunc))) << endl;

	return 0;
}

 위 코드는 함수 객체를 알고 있다면 특별히 어려운 건 없지만 햇갈릴 수 있으므로 간단히 해석을 해보겠다.

 

unary_function 클래스를 상속해 어댑터 적용이 가능한 클래스 템플릿을 만든다.

Pred 클래스는 함수 객체 클래스이다.

즉, 함수 포인터를 멤버로 가지고 있으며 () 연산자를 오버로딩해 함수 객체로 사용할 수 있다.

 

Pred 클래스와 같이 정의가 끝났으면 predfunc 함수를 객체화 시켜야 한다.

객체화는 Adapt 함수 템플릿과 같은 방식으로 진행한다. 함수 템플릿 Adapt는 전달받은 인자를 통해 자료형을 유추한다.

 

유추한 자료형을 기반으로 Pred 클래스 템플릿에 템플릿 인자(Rtype, Atype)와  predfunc 함수 포인터를 각각 전달하면서 Pred 함수 객체가 생성되는 것이다. 생성이 이루어지고 return 을 통해 not1 함수 템플릿에 Pred 객체가 전달 된다.

 

이후 count_if 함수를 통해 컨테이너를 순회하면서 not1 연산의 결과가 참인 값을 카운트한다.

 

 

'Programming > C++ & STL' 카테고리의 다른 글

정적 함수, 멤버 함수 포인터  (0) 2021.01.20
바인더(binder)  (0) 2021.01.16
객체 포인터의 참조 관계  (0) 2021.01.15

댓글