함수 객체 ( functor ; 펑터 )

Crat3 ㅣ 2023. 10. 6. 17:13

0. 함수 포인터의 단점

- 시그니처가(타입이) 일치하지 않으면 사용할 수 없다.

- 특정 상태(값)를 가질 수 없음.

 

 

1. 함수 객체 (functor)

함수를 호출하는 용도로 사용하는 객체.

 

 

2. 문법

class Functor
{
public:
	// 연산자 오버로딩
	void operator() ()
	{
		cout << "Functor Test" << endl;
		// 맴버 변수를 출력함
		cout << _value << endl;
	}

public:
	int _value;
};


int main()
{
	Functor func;
	func._value = 10;
	func();
}

특정 동작을 수행하는 멤버 함수를 가지는 클래스를 만들어 사용한다.

일반적으로 괄호 연산자를 오버로딩하여 사용하게 된다.

 

 

3. 템플릿 문법과 함수 객체

템플릿 문법을 사용하여 함수 객체를 재사용할 수 있다.

struct AddStruct
{
public:
	int operator()(int a, int b)
	{
		return a + b;
	}
};

template<typename T>
int Test(int a, int b, T func)
{
	return func(a, b);
}


int main()
{
	AddStruct func;
	Test(10, 20, func);
}

위의 코드를 통해 a와 b를 더하는 역할을 수행했다면, func의 시그니처를 다르게 지정하여 곱하기를 연산할 수도 있다.

struct MultiplyStruct
{
	int operator()(int a, int b)
	{
		return a * b;
	}
};

template<typename T>
int Test(int a, int b, T func)
{
	return func(a, b);
}


int main()
{
	MultiplyStruct func;
	Test(10, 20, func);
}

 

4. 활용

여러 함수 객체를 컨테이너(큐, 벡터, 리스트) 내에 사용하는 상황을 생각해보자

class AddClass
{
public:
	int operator()(int a, int b)
	{
		return a + b;
	}
};

class MultiplyClass
{
	int operator()(int a, int b)
	{
		return a * b;
	}
};

template<typename T>
int Test(int a, int b, T func)
{
	return func(a, b);
}


int main()
{
	queue< ? ? ? > q;
}

상황에 따라 AddClass 펑터 혹은 MultiplyClass 펑터를 사용하고자 하면

위의 q의 타입에는 무엇이 와야하는지에 대한 의문이 생길 수 있다.

이럴 때에는 다형성을 사용하여 상위 클래스로 묶어주면 된다.

class Functors
{
public:

};

class AddClass : public Functors
{
public:
	int operator()(int a, int b)
	{
		return a + b;
	}
};

class MultiplyClass : public Functors
{
	int operator()(int a, int b)
	{
		return a * b;
	}
};

template<typename T>
int Test(int a, int b, T func)
{
	return func(a, b);
}


int main()
{
	queue<Functors> q;
}

 

'복습' 카테고리의 다른 글

오른값 참조 (r-value Reference)  (0) 2023.10.11
람다 표현식 (Lambda)  (0) 2023.10.11
함수 포인터  (0) 2023.10.06
우선순위 큐 (priority_queue)  (1) 2023.10.05
가위 바위 보  (0) 2023.08.07