공부 중 메모/C++ STL(Book : 뇌를 자극하는 STL)

1_함수 객체

라이피 (Lypi) 2018. 7. 26. 18:56
반응형
#include <iostream>
using std::cout;
using std::endl;
using std::cin;

//first, second, third, forth, fifth_functor, fifth_stl, sixth

#define problem

//a. 함수 객체는 함수처럼 호출 가능한 클래스 객체이다. 
//b. 함수 객체는 함수처럼 사용할 수 있으면서도 상태를 가질 수 있다.
//c. 객체가 함수처럼 동작하려면 '()'연산자를 재정의해야 한다.

#ifdef first

void print()
{
	cout << "전역 함수" << endl;
}

struct Functor
{
	void operator() ()
	{
		cout << "함수 객체" << endl;
	}
};

int main()
{
//	functor print;
//
//	//이름이 같으면 함수 객체가 우선시된다.
//	print();     //멤버 함수 호출 (functor.operator()와 같음)
//	::print();   //전역 함수 호출

	Functor functor;

	print();    //전역 함수 호출
	functor();  //멤버 함수 호출
}

#endif

//매개변수 리스트를 갖는 함수 객체 만들기

#ifdef second

void printAdd(int a, int b)
{
	cout << "전역 함수 : ";
	printf("%d+%d=%d\n", a, b, a + b);
}

struct Functor
{
	void operator() (int a, int b)
	{
		cout << "함수 객체 : ";
		printf("%d+%d=%d\n", a, b, a + b);
	}
};

int main()
{
	Functor functorAdd;

	printAdd(2, 4);
	functorAdd(2, 4);
}

#endif

//함수 객체의 장점
//1. 일반 함수와는 다르게 다른 멤버 변수와 멤버 함수를 가질 수 있다.
//2. 함수 객체의 시그니처가 같아도 객체 타입이 다르면 전혀 다른 타입으로 인식한다.
//3. 일반 함수보다 함수 객체가 더 빠르다.
//4. 일반 함수의 함수 포인터는 인라인 될 수 없지만 함수 객체는 인라인 될 수 있고, 컴파일러가 쉽게 최적화 할 수 있다.

#ifdef third

class Adder
{
	int total;

public:
	explicit Adder(int n = 0) : total(n) {}
	
	//클래스 내부에 정의었으므로 인라인 함수.
	int operator() (int n) 
	{
		return total += n;
	}
};

class Miner
{
	int total;

public:
	explicit Miner(int n = 0) : total(n) {}
	int operator() (int n)
	{
		return total -= n;
	}
};

int main()
{
	//멤버 변수를 갖는 함수 객체
	Adder add(0); // 초깃값 0
	
	cout << add(10) << endl;
	cout << add(20) << endl;
	cout << add(30) << endl;

	//(함수)객체끼리의 대입 
	Adder add_a(10); // 초깃값 0
	Miner min(0); // 초깃값 0

	add = add_a;
	cout << add(0) << endl;

	//시그니처는 같지만 객체 타입이 다르므로 (기본적으로) 대입이 안된다.
	//add = min;
}

#endif

//콜백 함수 예제를 함수 객체를 사용하여 변경한 것
//for_each() 알고리즘에 함수가 아닌 함수 객체를 전달할 수도 있다는 것을 보여준다.
//for_each() 알고리즘이 템플릿으로 구현되어 있기 때문이다.

#ifdef forth

#include <algorithm>
using std::for_each;

//클라이언트 함수 객체들
struct Functor_a {
	void operator() (int a) {
		cout << a << ' ';
	}
};

struct Functor_b {
	void operator() (int b) {
		cout << b * b << ' ';
	}
};

struct Functor_c {
	void operator() (int c) {
		cout << "정수 : " << c << endl;
	}
};

int main()
{
	int arr[5] = { 10,20,30,40,50 };

	for_each(arr, arr + 5, Functor_a());
	cout << endl << endl;
	for_each(arr, arr + 5, Functor_b());
	cout << endl << endl;
	for_each(arr, arr + 5, Functor_c());
	cout << endl << endl;
}


#endif

//bool형을 반환하는 less와 greater함수 객체. 
//조건자(predicate)

#ifdef fifth_functor

//함수들
bool greater_f(int a, int b)
{
	return a > b;
}

bool less_f(int a, int b)
{
	return a < b;
}


//함수 객체들
struct functor_greater
{
	bool operator() (int a, int b)
	{
		return a > b;
	}
};

struct functor_less
{
	bool operator() (int a, int b)
	{
		return a < b;
	}
};


int main()
{
	functor_greater greater;

	functor_less less;

	int a = 10;
	int b = 20;

	cout << "전역 함수 호출" << endl;
	cout << less_f(a, b) << endl;
	cout << greater_f(a, b) << endl;
	cout << endl;

	cout << "함수 객체 호출" << endl;
	cout << less(a, b) << endl;
	cout << greater(a, b) << endl;
	cout << endl;

	//functor_less()와 func_greater(0)은 생성자를 호출한 것.
	cout << "임시 객체를 이용해 함수 객체 호출" << endl;
	cout << functor_less() (a,b) << endl;
	cout << functor_greater() (a, b) << endl;
	cout << endl;

	cout << "명시적 함수 호출" << endl;
	cout << less.operator()(a, b) << endl;
	cout << greater.operator()(a, b) << endl;
	cout << endl;
}

#endif

//STL의 less와 greater 함수 객체 사용

#ifdef fifth_stl

#include <functional>
using std::less;
using std::greater;

//클래스 템플릿으로 되어있다.
typedef less<int> Less;
typedef greater<int> Greater;

int main()
{
	Less iLess;
	Greater iGreater;

	int a = 10;
	int b = 20;

	cout << "함수 객체 호출" << endl;
	cout << iLess(a, b) << endl;
	cout << iGreater(a, b) << endl;
	cout << endl;

	cout << "임시 객체를 이용해 함수 객체 호출" << endl;
	cout << Less() (a, b) << endl;
	cout << Greater() (a, b) << endl;
	cout << endl;

	cout << "명시적 함수 호출" << endl;
	cout << iLess.operator()(a, b) << endl;
	cout << iGreater.operator()(a, b) << endl;
	cout << endl;

	cout << "임시 객체를 이용한 명시적 함수 호출" << endl;
	cout << Less().operator()(a, b) << endl;
	cout << Greater().operator()(a, b) << endl;
	cout << endl;
}

#endif

//plus(), minus()
//함수, 함수 객체, STL 비교

#ifdef sixth

#include <functional>
using std::plus;
using std::minus;

int plus_f(int a, int b)
{
	return a + b;
}

int minus_f(int a, int b)
{
	return a - b;
}

struct functor_plus
{
	int operator() (int a, int b)
	{
		return a + b;
	}
};

struct functor_minus
{
	int operator() (int a, int b)
	{
		return a - b;
	}
};

int main()
{
	functor_plus Plus;
	functor_minus Minus;

	int a = 10;
	int b = 20;

	cout << "함수 사용" << endl;
	cout << plus_f(a, b) << endl;
	cout << minus_f(a, b) << endl;
	cout << endl;

	cout << "함수 객체 사용" << endl;
	cout << Plus(a, b) << endl;
	cout << Minus(a, b) << endl;
	cout << endl;

	cout << "STL 사용" << endl;
	cout << plus<int>() (a, b) << endl;
	cout << minus<int>() (a, b) << endl;
	cout << endl;
}
#endif

//함수 객체의 구현 방법과 사용법을 잘 알아두자.

//문제풀이
#ifdef problem

//1. 함수처럼 호출 가능한 클래스 객체를 가리켜 함수 객체라 합니다.
//2. 함수처럼 호출 가능한 클래스 객체는 operator()를 재정의하여 생성합니다.


struct equal
{
	bool operator() (int a, int b)
	{
		if (a == b) { return true; }
		else { return false; }
	}
};

struct Adder
{
	int operator() (int a, int b)
	{
		return a + b;
	}
};

int main()
{
	equal cmp;

	if (cmp(10, 20)) {
		cout << "같다" << endl;
	}
	else {
		cout << "다르다" << endl;
	}

	Adder add;

	int sum = add(10, 20);
	cout << "sum = " << sum << endl;
}

#endif


반응형