C, C++ の関数ポインタ 自分用メモ

# いつも忘れてしまうので、自分用メモ
## 1.基本形

```c:sample1.c
#inclide <stdio.h>
double Calc(int a, double f)
{
    return a * f;
}

int main()
{
    // 初期化
    double (*pFunc)(int, double) = Calc;

    // 実行
    double result = (*pFunc)(3, 2.5);
    printf("%f\n", result);
}
```

## 2. C++ クラス内のメンバ関数を関数ポインタで扱いたい
```c++:sample2.cpp
#include <iostream>

class CHoge
{
public:
    CHoge() {}
    ~CHoge() {}

    void FuncAll()
    {
        // 初期化
        int (CHoge:: * pFunc1)(int) = &CHoge::func1;
        int (CHoge:: * pFunc2)(int) = &CHoge::func2;
        int (CHoge:: * pFunc3)(int) = &CHoge::func3;

        // 実行
        std::cout << (this->*pFunc1)(3) << std::endl;
        std::cout << (this->*pFunc2)(1) << std::endl;
        std::cout << (this->*pFunc3)(4) << std::endl;
    }

private:
    int func1(int n) { return n; }
    int func2(int n) { return n * 2; }
    int func3(int n) { return n * 3; }
};

int main()
{
    CHoge hoge;
    hoge.FuncAll();
}
```
## 3. vector で回してみる
```c++:sample3.cpp
#include <iostream>
#include <vector>

class CHoge
{
public:
    CHoge() {}
    ~CHoge() {}

    void FuncAll()
    {
        // 初期化
        std::vector<int (CHoge::*)(int)> vecFuncPtr = {
            &CHoge::func1,
            &CHoge::func2,
            &CHoge::func3,
        };
        
//      auto の方が楽
//      for (int (CHoge::* pFunc)(int) : vecFuncPtr) {
        for (auto pFunc : vecFuncPtr) {
            std::cout << (this->*pFunc)(3) << std::endl;
        }
    }

private:
    int func1(int n) { return n; }
    int func2(int n) { return n * 2; }
    int func3(int n) { return n * 3; }
};

int main()
{
    CHoge hoge;
    hoge.FuncAll();
}
```

## 4. std::function, bind を使ってみる
```c++:sample4.cpp
#include <iostream>
#include <functional>

class CHoge
{
public:
    CHoge() {}
    ~CHoge() {}

    void FuncAll()
    {
        // 初期化
        auto tfunc1 =
            std::bind(&CHoge::func1, this, std::placeholders::_1);
        auto tfunc2 =
            std::bind(&CHoge::func2, this, std::placeholders::_1);
        auto tfunc3 =
            std::bind(&CHoge::func3, this, std::placeholders::_1);

        // 実行
        std::cout << tfunc1(3) << std::endl;
        std::cout << tfunc2(1) << std::endl;
        std::cout << tfunc3(4) << std::endl;
    }

private:
    int func1(int n) { return n; }
    int func2(int n) { return n * 2; }
    int func3(int n) { return n * 3; }
};

int main()
{
    CHoge hoge;
    hoge.FuncAll();
}
```
## 5. 同様に vector で回してみる

```c++:sample5.cpp
#include <iostream>
#include <functional>
#include <vector>

class CHoge
{
public:
    CHoge() {}
    ~CHoge() {}

    void FuncAll()
    {
        // 初期化
        std::vector< std::function<int(int)> > vecFunction =
        {
            std::bind(&CHoge::func1, this, std::placeholders::_1),
            std::bind(&CHoge::func2, this, std::placeholders::_1),
            std::bind(&CHoge::func3, this, std::placeholders::_1),
        };

        // 実行
        //  for (std::function<int(int)> tFunc : vecFunction) {
        for (auto tFunc : vecFunction) {
            std::cout << tFunc(3) << std::endl;
        }
    }

private:
    int func1(int n) { return n; }
    int func2(int n) { return n * 2; }
    int func3(int n) { return n * 3; }
};

int main()
{
    CHoge hoge;
    hoge.FuncAll();
}
```
## 6. ラムダ式で書いてみる
```c++:sample6.cpp
#include <iostream>
#include <functional>

class CHoge
{
public:
    CHoge() {}
    ~CHoge() {}

    void FuncAll()
    {
        // 初期化
        auto lamda1 = [this](int i) { return func1(i); };
        auto lamda2 = [this](int i) { return func2(i); };
        auto lamda3 = [this](int i) { return func3(i); };

        // 実行
        std::cout << lamda1(3) << std::endl;
        std::cout << lamda2(1) << std::endl;
        std::cout << lamda3(4) << std::endl;
    }

private:
    int func1(int n) { return n; }
    int func2(int n) { return n * 2; }
    int func3(int n) { return n * 3; }
};

int main()
{
    CHoge hoge;
    hoge.FuncAll();
}
```
## 7. ラムダ式で書いて vector
```c++:sample7.cpp
#include <iostream>
#include    <vector>
#include    <functional>

class CHoge
{
public:
    CHoge() {}
    ~CHoge() {}

    void FuncAll()
    {
        // 初期化
        std::vector<std::function<int(int)>> vecFunc = {
            [this](int i) { return func1(i); },
            [this](int i) { return func2(i); },
            [this](int i) { return func3(i); },
        };

        // 実行
        for(auto func : vecFunc) {
            std::cout << func(3) << std::endl;
        }
    }

private:
    int func1(int n) { return n; }
    int func2(int n) { return n * 2; }
    int func3(int n) { return n * 3; }
};

int main()
{
    CHoge hoge;
    hoge.FuncAll();
}
```
## 8.ラムダ式 別解1
こんな書き方もあるよと。そろそろ main() は省きます。

```c++:sample8.cpp
class CHoge
{
public:
    CHoge() {}
    ~CHoge() {}

    void FuncAll()
    {
        // 初期化
        auto pFunc1 = [](CHoge* p, int n) { return p->func1(n); };
        auto pFunc2 = [](CHoge* p, int n) { return p->func2(n); };
        auto pFunc3 = [](CHoge* p, int n) { return p->func3(n); };

        // 呼び出し
        std::cout << pFunc1(this, 1) << std::endl;
        std::cout << pFunc2(this, 2) << std::endl;
        std::cout << pFunc3(this, 3) << std::endl;
    }

private:
    int func1(int n) { return n; }
    int func2(int n) { return n * 2; }
    int func3(int n) { return n * 3; }
};
```

## 9.ラムダ式別解2

```c++:sample9.cpp

class CHoge
{
public:
    CHoge() {}
    ~CHoge() {}

    void FuncAll()
    {
        // 初期化
        std::vector<std::function<int(CHoge*, int)>> vecFunc = {
            { [](CHoge* p, int n) { return p->func1(n); } },
            { [](CHoge* p, int n) { return p->func2(n); } },
            { [](CHoge* p, int n) { return p->func3(n); } },
        };

        // 呼び出し
        for (auto func : vecFunc) {
            std::cout << func(this, 3) << std::endl;
        }
    }

private:
    int func1(int n) { return n; }
    int func2(int n) { return n * 2; }
    int func3(int n) { return n * 3; }
};
```

## 10.感想
う～ん。どうだろ? 僕は昔の書き方(sample2, sample3)で慣れ親しんだのでつい書いちゃうけど、今風なら sample6, sample7 あたりがすっきりしているかな。