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 |