C , C++, C#

[C/C++] Callable, std::function

vhxpffltm 2020. 1. 14. 22:31
반응형

Callable이란 호출할 수 있는 모든것을 나타낸다. 

 

C++에서도 함수를 호출하는데 여러 방법이 있는데 그것을 알아볼 것이다.

 

참고로 '()' 을 붙여서 사용한다. 

 

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
32
33
34
35
36
37
38
39
40
41
42
#include<iostream>
#include<functional>
#include<string>
 
class info
{
public:
    void operator()(int a, int b) { std::cout << "a + b = " << a + b << std::endl; }
};
 
struct info2 {
    void operator()(char a) { std::cout << "fun2 호출 " << a << std::endl; }
};
 
int fun1(const std::string& a) {
    std::cout << "fun1 호출 : " << a << std::endl;
    return 0;
}
 
class A {
    int a;
public:
    A(int i) : a(i) {}
    int A_fun() {
        std::cout << "비상수 함수 데이터 : " << a + 1 << std::endl;
        return a;
    }
    int A_Const_fun() const {
        std::cout << "상수 함수 데이터 : " << a << std::endl;
        return a;
    }
};
 
int main() {
    info in;
    auto a = [](int a, int b) {std::cout << "a * b = " << a * b << std::endl; }; // 람다함수
    in(12);
    in.operator()(15);
    a(22);
    std::cout << "\n\n";
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

 

 

위 코드에서 in은 info의 객체이다. 이 객체를 함수처럼 ()을 사용하여 호출할 수 있다. 

실제로는 in.operator()(1,2) 와 같은 표현이다. 

코드가 쉽기에 결과는 쉽게 확인할 수 있을 것이다. 위의 코드에 람다함수도 있지만 이것은 나중에 설명하도록 하자.

 

 

std :: function

이러한 Callable 들을 객체의 형태로 보관할 수 있는 std::function 이라는 클래스를 제공한다. C 에서의 함수 포인터는 진짜 함수들만 보관할 수 있는 객체라고 볼 수 있다면 이 std::function 의 경우 함수 뿐만이 아니라 모든 Callable 들을 보관할 수 있는 객체이다.

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include<iostream>
#include<functional>
#include<string>
 
class info
{
public:
    void operator()(int a, int b) { std::cout << "a + b = " << a + b << std::endl; }
};
 
struct info2 {
    void operator()(char a) { std::cout << "fun2 호출 " << a << std::endl; }
};
 
int fun1(const std::string& a) {
    std::cout << "fun1 호출 : " << a << std::endl;
    return 0;
}
 
class A {
    int a;
public:
    A(int i) : a(i) {}
    int A_fun() {
        std::cout << "비상수 함수 데이터 : " << a + 1 << std::endl;
        return a;
    }
    int A_Const_fun() const {
        std::cout << "상수 함수 데이터 : " << a << std::endl;
        return a;
    }
};
 
int main() {
    //std :: function
    std::function<int(const std::string&)> f1 = fun1;
    std::function<void(char)> f2 = info2();
    std::function<void()> f3 = []() {std::cout << "fun3 호출 " << std::endl; };
    f1("KOREA");
    f2('A');
    f3();
    //function 객체는 템플릿 인자로 전달 받은 함수의 타입을 갖게된다. <인자로 전달받은 함수타입,리턴값(함수의 인자)>
    //ex) int(const std::~~) 리턴값(인자)
}
 
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

 

function은 위와 같이 사용할 수 있다. 

    std::function<int(const std::string&)> f1 = fun1;

    std::function<void(char)> f2 = info2();

    std::function<void()> f3 = []() {std::cout << "fun3 호출 " << std::endl; };

 

위의 코드를 보면 <> 안의 템플릿 인자로 전달 받은 함수의 타입을 본다. 

첫 번째 라인을 보면 int형을 가지고 const string&을 파라미터로 가지게 된다 이것을 형식에 맞게 사용하여 함수를 정의한다.

두 번째도 void operator()(char a) 으로 voidchar형을 받고 마지막은 타입도 인자도 없기때문에 비어있도록 정의하면 된다.

아래는 출력 결과이다.

 

 

 

맴버 함수의 경우 그냥 function에 넣으면 this가 무엇인지 모르는 경우가 발생한다. 이를 위해 전달할 때 객체에 대한 정보도 추가적으로 전달해야 한다. &A:: 이렇게 객체에 대한 정보를 추가한다.

1
2
3
4
5
6
7
8
9
10
//맴버함수의 경우
    //맴버함수 내에서 ths의 경우 자신을 호출한 객체를 의미, 맴버함수를 그냥 function에 넣으면 this가 뭔지 모르는 문제 발생
    //전달할때 객체에 대한 정보도 추가로 전달해야함
    A n(5);
    std::function<int(A&)> ff1 = &A::A_fun;
    std::function<int(const A&)> ff2 = &A::A_Const_fun;
    ff1(n);
    ff2(n);
 
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

 

 

Reference

https://modoocode.com/254

 

 

 

반응형

'C , C++, C#' 카테고리의 다른 글

[C/C++] Mutex  (0) 2020.02.22
[C/C++] Thread  (0) 2020.01.19
[C/C++] weak_ptr  (0) 2020.01.09
[C/C++] Shared_ptr  (0) 2020.01.06
[C/C++] unique_ptr  (0) 2019.12.28