프로그래밍응용/Modern & STL

함수 포인터를 대체하는 std::function

photoner 2021. 2. 8. 00:25
728x90
반응형

std::function이 필요한 이유부터 설명하겠다.

위는 함수 포인터로 객체의 멤버함수를 가리킬려고 온갖 발악을 하지만.. 되지 않는 광경을 보고 있다. 35번 줄은 말도 안되기 때문에 에러부터 난다.

왜 에러가 날까?

1. = 연산자를 기준으로 타입이 맞지 않다.

2. C++에서는 객체의 멤버 함수의 이름은 해당 함수의 주소 값으로 변환되지 않는다. 즉, 객체 멤버 함수의 이름으로는 함수의 주소 값을 알 수 없다는 것이다.

3. 설령, 주소를 어떻게 넣는다고 하더라도, 해당 주소의 함수가 어떤 객체의 것인지 알 수가 없다.

뭐 아무튼 그래서 36번 라인과 40번 라인처럼 기이한 방법으로 사용한다... 나의 의도가 아니다 ㅋㅋㅋㅋㅋ

이런 설정인데, 예로 보겠다.

예 중 하나인데, 번호 순서대로 읽으면 되며, 배열 형태로도 가능하며, 단일 형태로도 할당이 가능하다.

위의 예를 호출하는 문장이다.

아래와 같이 객체를 () 연산자 오버로딩한 객체, functor 또한 std::function으로 담아낼 수 있다.

 

그리고 또한 멤버 함수 또한 받을 수 있는데 이 또한 예제로 보겠다.

 

아래에 전체 코드와 실행 결과를 확인해보겠다. 먼저, 함수 포인터를 이용한 예제이다.

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
#include <iostream>
 
using namespace std;
 
class A
{
        private:
                int n;
        public:
                A(int a):n(a)
                {
                }
                void memberFunc(void)
                {
                        cout<<"n:"<<this->n<<endl;
                        return;
                }
};
 
void normalFunc(void)
{
        cout<<"call()!!"<<endl;
        return;
}
 
int main(void)
{
        A a(100);
 
        void (*nfunc)(void);
        void (*mfunc)(void);
        void (A::*mmfunc)(void);
 
        nfunc = normalFunc;
        // mfunc = a.memberFunc;
        mmfunc = &A::memberFunc;
 
        nfunc();
        // mfunc();
        (a.*mmfunc)();
 
        return 0;
}
cs

다음은 std::function에 대한 전체 예제이다.

 

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <functional>
#include <string>
#include <iostream>
 
class A
{
        private:
                std::string name;
        public:
                A(const char * _name)
                {
                        this->name = _name;
                }
                void AFunc()
                {
                        std::cout<<"AFunc() Call! name : "<<this->name<<std::endl;
                        return;
                }
};
 
struct S
{
        void operator()(const std::string& str)
        {
                std::cout<<"S::operator() Call! : "<<str<<std::endl;
                return;
        }
};
 
int main(void)
{
        A a("Kim");
        A b("Yoo");
 
        int m = 100;
 
        std::function<int(intint)> operators[] =
        {
                [](int n1, int n2) -> int { return n1 + n2; },
                [](int n1, int n2) -> int { return n1 - n2; },
                [](int n1, int n2) -> int { return n1 * n2; },
                [](int n1, int n2) -> int { return n1 / n2; },
                [](int n1, int n2) -> int { return n1 % n2; },
                [m](int num1, int num2) -> int { return m*num1 + m*num2; },
        };
 
        std::function<void(const std::string& str)> f1 = S();
 
        std::function<void(A&)> FirstNameFunc = &A::AFunc;
 
        std::cout<<"operators[0] : "<<operators[0](55)<<std::endl;
        std::cout<<"operators[1] : "<<operators[1](55)<<std::endl;
        std::cout<<"operators[2] : "<<operators[2](55)<<std::endl;
        std::cout<<"operators[3] : "<<operators[3](55)<<std::endl;
        std::cout<<"operators[4] : "<<operators[4](55)<<std::endl;
        std::cout<<"operators[5] : "<<operators[5](55)<<std::endl;
 
        std::string str = "Hi Hello~";
        f1(str);
        FirstNameFunc(a);
        FirstNameFunc(b);
 
        return 0;
}
cs

728x90
반응형