読者です 読者をやめる 読者になる 読者になる

とくにあぶなくないRiSKのブログ

危ないRiSKのブログだったかもしれない。本当はRiSKだけどググラビリティとか取得できるIDの都合でsscriskも使ったり。

DとC++で関数ポインタとデリゲートを使う方法

D C++

まずD言語で関数ポインタとデリゲートを使ってみる。

import std.stdio;

void func(int n) { writeln("func(", n, ")"); }

class C
{
 void mem_func(int n) { writeln("C.mem_func(", n, ")"); }
}

void main()
{
 void function(int) fp = &func; // 関数ポインタ
 fp(0);

 C c = new C;
 void delegate(int) dg = &c.mem_func; // デリゲート
 dg(1);
}

実行結果:

func(0)
C.mem_func(1)

これと同じ事を C++ でもやってみる。
その前に…。デリゲートの本性は環境と関数ポインタを束ねたもの。上の例では,c (this)が環境としてメンバ関数へのポインタと一緒にdgへ渡されている。で,C++で同じ事をするには std::bind と std::function を使えばおk。

#include<iostream>
#include<functional>

void func(int n) { std::cout << "func(" << n << ")" << std::endl; }

class C
{
public:
 void mem_func(int n) { std::cout << "C::mem_func(" << n << ")" << std::endl; }
};

int main()
{
 void (*fp)(int) = &func; // 関数ポインタ
 fp(0);

 C c;
 std::function<void(int)> dg = std::bind(&C::mem_func, &c, std::placeholders::_1); // デリゲート
 dg(1);
}

実行結果:

func(0)
C::mem_func(1)

あるいはstd::bindの代わりにラムダを使う。

#include<iostream>
#include<functional>

class C
{
public:
 void mem_func(int n) { std::cout << "C::mem_func(" << n << ")" << std::endl; }
};

int main()
{
 C c;
 std::function<void(int)> dg = [&c](int n){ c.mem_func(n); }; // デリゲート
 dg(2);
}

実行結果:

C::mem_func(2)

さらに auto も使えば std::function もいらなくなる。

#include<iostream>

class C
{
public:
 void mem_func(int n) { std::cout << "C::mem_func(" << n << ")" << std::endl; }
};

int main()
{
 C c;
 auto dg = [&c](int n){ c.mem_func(n); }; // デリゲート
 dg(3);
}

実行結果:

C::mem_func(3)