일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- enumasByue
- moreeffectiveC++
- dataasset
- 알고리즘
- 애셋로드
- 데이터애셋
- stl
- UML관련
- 람다
- 정렬알고리즘
- map
- 람다사용정렬
- 프로그래머스
- 선택정렬
- C++
- 언리얼엔진구조체
- 델리게이트
- 정렬
- 강참조
- unorder_map
- 자료구조
- UELOG
- 크리티컬섹션
- BFS
- UE_LOG
- C++최적화
- UE4 커스텀로그
- 스마트포인터
- 언리얼가비지컬렉터
- 약참조
- Today
- Total
기억을 위한 기록들
[CPP]std::function에 관하여 본문
<functional> 헤더 파일에 정의된 std::function 템플릿을 이용하면
1. 함수를 가리키는 타입(함수 포인터)
2. 함수 객체
3. 람다 표현식
세개를 비롯하여 호출 가능한 모든 대상을 가리키는 타입을 생성할 수 있다.
std::function은 다형성 함수 래퍼(polymorphic function wrapper)라고도 불리며, 함수 포인터로도 사용할 수도 있고,
콜백을 구현하는 함수를 나타내는 매개변수와 사용할 수도 있다.
std::function<R(ArgTypes...)>
R은 리턴타입이고, ArgTypes는 각각을 콤마로 구분한 매개변수의 타입 목록이다.
예제 1) 함수포인터 형식
void func(int num, const string& str)
{
cout<< num <<", "<<std<<endl;
}
int main(){
std::function<void(int, const string&)> f1 = func;
f1(1, "test");
return 0;
}
이 예제에서는 auto 키워드를 사용하면 f1앞에 구체적으로 안 써도 되긴 한다. 더 간결하게 표현이 가능하다.
하지만 이렇게 하면 컴파일러는 f1의 타입이 std::function이 아니라 함수 포인터라고 판단한다.
그래서 void(*f1) (int, const string&)라고 반환해버린다.
auto f1 = func;
예제 2)
std::function 타입은 함수 포인터처럼 작동하기 때문에 표준 라이브러리 알고리즘에 인수로 전달 가능하다.
find_if() 알고리즘에 이를 적용한 예는 다음과 같다.
bool IsEven(int num)
{
return num%2 == 0;
}
int main()
{
vector<int> vec{1,2,3,4,5};
std::function<bool<int>> fcn = IsEven;
auto result = find_if(cbegin(vec),cend(vec), fcn);
if( result != cend(vec))
cout<<"첫 짝수는 : "<<*result<<endl;
else
cout<< "짝수를 찾을 수 없습니다."<<endl;
return 0;
}
이 예제들 까지를 보면 굳이 std::function을 사용할 필요가 없다는 생각이 들 수도 있다.
std::function의 진가는 콜백을 클래스의 멤버 변수에 저장해야 할 때와 함수 포인터를 매개변수로 받아야 할 때도 유용하다.
예제 3) 함수포인터 , 람다 표현식
void process(const vector<int>& vec, function<void(int)> f)
{
for(auto& i : vec)
{
f(i);
}
}
void print(int num)
{
cout<< num << " ";
}
int main()
{
vector<int> vec{0,1,2,3,4,5};
//print를 함수포인터로 전달해서 호출
process(vec,print);
cout<<endl;
//람다 표현식을 std::function 매개변수의 값으로 지정하는 예
// std::function의 진가!
// 일반 함수 포인터로는 이렇게 처리할 수 없다.
int sum = 0;
process(vec,[&sum](int num) {sum +=num;});
cout<<"sum = "<< sum <<endl;
return 0;
}
출력 결과
0 1 2 3 4 5
sum = 15
콜백 매개변수로 std::function을 사용하지 않고, 함수 템플릿으로 만들어도 된다.
template<typename F>
void processTemplate(const vector<int>& vec, F f)
{
for(auto& i:vec)
{
f(i);
}
}
이렇게 정의한 함수 템플릿은 비템플릿 process() 함수와 기능이 같다.
processTemplate()는 일반 함수 포인터와 람다 표현식을 모두 받을 수 있다.
가능하면 함수객체보다는 람다 표현식을 사용하기 바란다. 람다 표현식이 코드를 작성하기 쉬울뿐만 아니라 읽거나 이해하기 쉽다.
이전에 정리한 람다식 관련
https://hyo-ue4study.tistory.com/324
참고서적 :
http://www.yes24.com/Product/Goods/77669043
'C & CPP' 카테고리의 다른 글
[CPP] const와 constexpr (0) | 2022.05.25 |
---|---|
[CPP] 함수 객체에 관하여 (0) | 2022.02.02 |
[CPP] using 과 typedef (0) | 2021.11.10 |
[CPP] C++에서의 1e-6f 란? (과학적 표기법/scientific notation) (0) | 2021.09.14 |
[CPP] C++ 최적화에 관하여 (3-3) (0) | 2021.08.22 |