struct plus
{
int operator()(int arg1, int arg2)
{
return arg1 + arg2;
}
};
int main()
{
plus p; // p는 객체
// p를 함수 처럼 사용
int n = p(1, 2); // p.operator()(1, 2)
std::cout << n << std::endl; // 3
}
template<class T>
struct plus
{
[[nodiscard]] constexpr
T operator()(const T& arg1, const T& arg2) const
{
return arg1 + arg2;
}
};
일반 함수는 동작은 있지만 상태가 없음
함수 객체는 동작(멤버 함수) 뿐 아니라 상태(멤버 데이터)도 가질 수 있음
멤버 함수 실행 중에 얻은 데이터는 멤버 데이터에 보관 가능
#include <bitset>
#include <random>
class URandom
{
std::bitset<10> bs;
bool recycle;
std::mt19937 randgen{ std::random_device{}() };
std::uniform_int_distribution<int> dist{0, 9};
public:
URandom(bool recycle = false) : recycle(recycle)
{
bs.set();
}
int operator()()
{
if (bs.none())
{
if (recycle)
bs.set();
else
return -1;
}
int k = -1;
while (!bs.test( k = dist(randgen) ));
bs.reset(k);
return k;
}
};
URandom urand;
int main()
{
for ( int i = 0; i < 15; i++)
std::cout << urand() << ", ";
std::cout << std::endl;
}
0~9까지의 랜덤수를 중복하지 않고 반환하는 코드
10개 다 꺼냈을 때 recycle이 true라면 초기화시키고 다시 랜덤 반환
#include <vector>
#include <algorithm>
class F
{
int value;
public:
F(int v) : value(v) {}
bool operator()(int n) const
{
return n % value == 0;
}
};
int main()
{
std::vector<int> v = { 1,2,6,7,8,3,4,5,9,10 };
int k = 3;
// F f(k);
auto r1 = std::find_if(v.begin(), v.end(), F(k)); // 임시객체 전달
std::cout << *r1 << std::endl;
}
일반 함수로는 불가능한 일을 함수 객체로 가능하게 함
함수 객체는 scope 내의 지역변수를 캡쳐할 수 있는 기능이 있음
인라인 함수 (Inline Function)
컴파일 시에 함수 호출식을 함수의 기계어 코드로 치환
컴파일 시간 동작하는 문법
인라인 함수와 함수 포인터
인라인 함수라도 함수 포인터에 주소를 담아서 사용하면 인라인 치환될 수 없음
int add1(int a, int b) { return a + b; }
inline int add2(int a, int b) { return a + b; }
int main()
{
int ret1 = add1(1, 2); // 호출
int ret2 = add2(1, 2); // 치환
int(*f)(int, int) = &add2;
f(1, 2); // 호출
}
void sort(int* x, int sz, bool(*cmp)(int, int))
{
for( int i = 0; i < sz-1; i++)
{
for ( int j = i + 1; j < sz; j++)
{
// if ( x[i] > x[j] )
if ( cmp(x[i], x[j]) )
std::swap(x[i], x[j]);
}
}
}
inline bool cmp1(int a, int b) { return a < b;}
inline bool cmp2(int a, int b) { return a > b;}
int main()
{
int x[10] = {1,3,5,7,9,2,4,6,8,10};
// sort(x, 10, &cmp1);
sort(x, 10, &cmp2);
for(auto e : x)
std::cout << e << ", ";
}
#include <algorithm>
struct Less
{
inline bool operator()(int a, int b) const { return a < b; }
};
struct Greater
{
inline bool operator()(int a, int b) const { return a > b; }
};
//void sort(int* x, int sz, bool(*cmp)(int, int) )
//void sort(int* x, int sz, Less cmp )
template<class T>
void sort(int* x, int sz, T cmp )
{
for( int i = 0; i < sz-1; i++)
{
for ( int j = i + 1; j < sz; j++)
{
if ( cmp(x[i], x[j]) )
std::swap(x[i], x[j]);
}
}
}
int main()
{
int x[10] = {1,3,5,7,9,2,4,6,8,10};
Less f1; f1(1, 2); sort(x, 10, f1);
Greater f2; f2(1, 2); sort(x, 10, f2);
}
sort() 함수를 템플릿으로 만들어 비교 정책 변경 가능하며 인라인 치환도 가능!
#include <algorithm>
#include <functional>
int main()
{
int x[10] = {1,3,5,7,9,2,4,6,8,10};
std::greater<int> f;
std::sort(x, x+10, f);
std::sort(x, x+10, std::greater<int>()); // 임시 객체
std::sort(x, x+10, std::greater()); // C++17
std::sort(x, x+10, std::greater{}); // 중괄호 표기법
}