Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- list
- unityAR
- map
- 지크슈
- semaphore
- 뮤텍스
- StartActivityForResult
- unorderedset
- 스핀락
- 바이너리세마포
- 안드로이드스튜디오
- C++
- Unity
- SpinLock
- 광유다
- Vector
- unorderedmap
- ARface
- 포톤
- 동기화
- 세마포
- 유니티
- photon
- mutex
- registerForActivityResult
- NotFoundException: String resource ID #0x0
- 유니티슈팅게임
- Java
- dependencyResilutionManagement
- 게임개발
Archives
- Today
- Total
와와
[ 씹어먹는 C++ ] 함수 객체 본문
함수 객체
Callable
()를 붙여서 호출할 수 있는 모든 것
Std::function
모든 Callable들을 보관할 수 있는 객체
#include <functional>
#include <iostream>
#include <string>
int some_func1(const std::string& a) {
std::cout << "Func1 호출! " << a << std::endl;
return 0;
}
struct S {
void operator()(char c) { std::cout << "Func2 호출! " << c << std::endl; }
};
int main() {
// 정의
std::function<int(const std::string&)> f1 = some_func1;
std::function<void(char)> f2 = S();
std::function<void()> f3 = []() { std::cout << "Func3 호출! " << std::endl; };
f1("hello");
f2('c');
f3();
}
std::function<리턴값 형태(인자값 형태)> 이름 = Callable;
와 같은 형태로 템플릿 인자로 전달 받을 함수의 타입을 가진다.
멤버 함수를 가지는 std::function
멤버 함수를 호출할 때, 구현 상 자신을 호출한 객체를 인자로 암묵적으로 받고 있다.
따라서 아래와 같은 코드를 실행하면 에러가 날 것이고, 해당 클래스의 객체를 인자로 보내주어야 올바르다.
잘못된 예시
#include <functional>
#include <iostream>
#include <string>
class A {
int c;
public:
A(int c) : c(c) {}
int some_func() { std::cout << "내부 데이터 : " << c << std::endl; }
};
int main() {
A a(5);
std::function<int()> f1 = a.some_func;
}
수정한 예시
#include <functional>
#include <iostream>
#include <string>
class A {
int c;
public:
A(int c) : c(c) {}
int some_func() {
std::cout << "비상수 함수: " << ++c << std::endl;
return c;
}
int some_const_function() const {
std::cout << "상수 함수: " << c << std::endl;
return c;
}
static void st() {}
};
int main() {
A a(5);
std::function<int(A&)> f1 = &A::some_func;
std::function<int(const A&)> f2 = &A::some_const_function;
f1(a);
f2(a);
}
멤버 함수들을 함수 객체로 -mem_fn
멤버 함수를 좀 더 쉽게 함수 객체로 변환하고 싶다면 std::mem_fn를 사용할 수 있다.
std::mem_fn은 멤버 함수 포인터를 받아 해당 멤버 함수를 호출할 수 있는 함수 객체를 생성한다.
#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>
using std::vector;
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(container.begin(), container.end(), size_vec.begin(),
std::mem_fn(&vector<int>::size));
for (auto itr = size_vec.begin(); itr != size_vec.end(); ++itr) {
std::cout << "벡터 크기 :: " << *itr << std::endl;
}
}
여기서 사용된 std::transform 함수는 <algorithm> 라이브러리에 있는 함수로, 각 원소들에 대해 인자로 전달된 함수를 실행시킨 다음 그 결과를 전달된 컨테이너에 넣어준다.
std::mem_fn(&vector<int>::size) 는 vector<int> 객체를 받아 그 객체의 size() 멤버 함수를 호출하는 함수 객체를 생성한다. 이 함수 객체는 transform 함수의 요구사항에 맞게 동작하여, 각 vector의 size를 구해 새로운 vector에 저장할 수 있게 된다.
std::bind
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() {
auto add_with_2 = std::bind(add, 2, std::placeholders::_1);
add_with_2(3);
// 두 번째 인자는 무시된다.
add_with_2(3, 4);
auto subtract_from_2 = std::bind(subtract, std::placeholders::_1, 2);
auto negate =
std::bind(subtract, std::placeholders::_2, std::placeholders::_1);
subtract_from_2(3); // 3 - 2 를 계산한다.
negate(4, 2); // 2 - 4 를 계산한다
}
bind는 기본적으로 인자를 값으로 복사한다. 따라서 레퍼런스로 인자를 전달하고 싶다면 std::ref나 std::cref를 사용해야 한다.
'개발 > C++' 카테고리의 다른 글
[ 씹어먹는 C++ ] C++의 멀티스레딩 (0) | 2024.10.13 |
---|---|
[ 씹어먹는 C++ ] 스마트 포인터 (unique_ptr/ shared_ptr/ weak_ptr) (0) | 2024.09.22 |
[씹어먹는 C++] 우측값 레퍼런스/ 이동 생성자/ Move 문법/ 완벽한 전달 (0) | 2024.09.20 |
[ 씹어먹는 C++ ] C++에서의 예외 처리 (2) | 2024.09.08 |
[ 씹어먹는 C++ ] 10. C++ STL (3) | 2024.09.01 |