Program Language/C & C++

[C++] Callable

야곰야곰+책벌레 2021. 10. 6. 11:09
728x90
반응형

Callable이란 이름 그대로 호출(Call)할 수 있는 모든 것을 의미한다. 대표적으로 함수가 있다. C++에서는 '()'를 붙여 호출할 수 있는 모든 것을 Callable이라고 한다.

1. operator

#include <iostream>
using namespace std;

struct SUM
{
	void operator()(int a, int b)
	{
		cout << a << " + " << b << " = " << a + b << endl;
	}
};

int main()
{
	SUM sum;
	sum(1, 2);
	return 0;
}

2. lamda

#include <iostream>
#include <functional>
#include <string>
using namespace std;

int sum_func(const string& a, const string& b)
{
	cout << a.c_str() << " + " << b.c_str() << " = " << stoi(a) + stoi(b) << endl;
	return stoi(a) + stoi(b);
}

struct SUM
{
	void operator()(int a, int b)
	{
		cout << a << " + " << b << " = " << a + b << endl;
	}
};

int main()
{
	function<int(const string&, const string&)> func1 = sum_func;
	function<void(int, int)> func2 = SUM();
	function<void()> func3 = []() { cout << "Call Func3" << endl; };

	func1("1", "2");
	func2(3, 4);
	func3();
	return 0;
}

3. function

#include <iostream>
#include <functional>
#include <string>
using namespace std;

class CSum
{
int m_nInt1;
int m_nInt2;

public:
	CSum(int a, int b) : m_nInt1(a), m_nInt2(b) {}

	int sum_func()
	{
		cout << m_nInt1 << " + " << m_nInt2 << " = " << m_nInt1 + m_nInt2 << endl;
		return m_nInt1 + m_nInt2;
	}
	int sum_func_const() const
	{
		cout << "const " << m_nInt1 << " + " << m_nInt2 << " = " << m_nInt1 + m_nInt2 << endl;
		return m_nInt1 + m_nInt2;
	}
};

int main()
{
	CSum S(1, 2);
	//error C3867: 'CSum::sum_func': non-standard syntax; use '&' to create a pointer to member
	//function<int()> func1 = S.sum_func;
	function<int(CSum&)> func1 = &CSum::sum_func;
	function<int(const CSum&)> func2 = &CSum::sum_func_const;

	func1(S);
	func2(S);
	return 0;
}

func1을 호출할 때, 함수의 입장에서 자신을 호출하는 객체가 무엇인지 알 수 없기 때문에 S의 정보도 추가 전달해야 한다. &CSum::sum_func와 같은 멤버 함수의 경우에는 함수의 이름만으로 그 주소 값을 전달할 수 없기 때문에 &연사자를 통해 명시적으로 주소 값을 전달해야 한다.

4. std::mem_fn

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

int main()
{
	vector<int> a(1);
	vector<int> b(2);
	vector<int> c(3);
	vector<int> d(4);

	vector<vector<int>> container;
	container.push_back(b);
	container.push_back(d);
	container.push_back(a);
	container.push_back(c);

	vector<int> size_vec(4);
	// std::transform에서 UnaryOperation이 멤버함수의 경우 컴파일 오류가 발생한다.
	// 멤버함수의 경우 명시적으로 표현해줘야 한다.
	// std::transform(container.begin(), container.end(), size_vec.begin(), &vector<int>::size);
	function<size_t(const vector<int>&)> sizeFunc = &vector<int>::size;
	std::transform(container.begin(), container.end(), size_vec.begin(), sizeFunc);

	for (auto itr = size_vec.begin(); itr != size_vec.end(); ++itr) {
		std::cout << "벡터 크기 :: " << *itr << std::endl;
	}
	
	return 0;
}

매번 function 객체를 만들어서 전달하는 것은 매우 귀찮은 일이라 C++에서는 mem_fn 함수를 추가하였다. 하지만 lamda 함수로도 쉽게 구현할 수 있기 때문에 자주 쓰이지는 않는다.

	//function<size_t(const vector<int>&)> sizeFunc = &vector<int>::size;
	std::transform(container.begin(), container.end(), size_vec.begin(), mem_fn(&vector<int>::size));

5. std::bind

#include <functional>
#include <iostream>

void add(int x, int y)
{
	std::cout << x << " + " << y << " = " << x + y << std::endl;
}

void subtract(int x, int y)
{
	std::cout << x << " - " << y << " = " << x - y << std::endl;
}

int main()
{
	// add 함수에 첫번째 인자를 2로 고정한 add_with_2 함수 생성
	auto add_with_2 = std::bind(add, 2, std::placeholders::_1);
	add_with_2(3);

	// 두 번째 인자는 무시된다.
	add_with_2(3, 4);

	// substract 함수에 두번째 인자를 2로 고정한 substract_from_2 함수 생성
	auto subtract_from_2 = std::bind(subtract, std::placeholders::_1, 2);
    // substract 함수 인자를 위치를 바꿘 negate 함수 생성
	auto negate =
		std::bind(subtract, std::placeholders::_2, std::placeholders::_1);

	subtract_from_2(3);  // 3 - 2 를 계산한다.
	negate(4, 2);        // 2 - 4 를 계산한다
	
	return 0;
}

  std::bind는 원래 함수에 특정 인자를 붙여 주는 역할을 한다. 주의할 점은 레퍼런스로 받을 경우인데 이때는 std::ref로 인자를 감싸 복사 가능한 레퍼런스로 변환해줘야 한다.

728x90
반응형

'Program Language > C & C++' 카테고리의 다른 글

[C++] recursive_mutex  (0) 2021.10.07
[C++] result_of  (0) 2021.10.06
[C++] condition_variable  (2) 2021.10.05
[C++] noexcept  (10) 2021.10.01
[C++] atomic  (6) 2021.10.01