みゆにゃんぶろぐ

ゲーム(開発)/カラオケ/サイクリング/コーヒーの話題多め。最近は不定期更新。なるべく毎週更新したい

11月24日

昨日今日と時間があったから、作品作りをしていた。現状は完成度50%くらいだと思う

12月の学内コンペに間に合うか激しく不安……(笑)

 

std::function

久々のプログラミングのメモ書き

作ってる作品の中にstd::functionを使う機会があったので、それについて書いていこうと思う

 

std::functionは関数アドレスを入れることができるオブジェクトである。関数ポインタみたいなものである

 

関数ポインタとは、いわば普通の変数にアドレスがあるように関数にもアドレスがあって、それを入れることができるポインタ変数のことである

関数名に()をつけるとその関数を実行するけど、関数名だけだとその関数のアドレスになる

関数ポインタの宣言方法は「(戻り値の型)(*関数ポインタ変数名)(引数の型、引数の型...)」となる。宣言した関数ポインタは、戻り値の型と引数の型と個数が一致する関数のみしか代入できない

実行するときは「関数ポインタ変数名();」で実行できる。上の場合だと「pfunc(10);」で実行できる。変数に()をつけられるのは、初めて見るときは不思議に見えるかもしれない

C++の標準関数でbsearch(探索)やqsort(ソート)を使用するときに、引数に関数ポインタを指定する必要があるので、覚えておくといいかも

 

ここで本題(笑)

さっきも書いたけど、std::functionは関数アドレスを入れることができるオブジェクトである。代入方法が色んなパターンがある

あ、std::functionを使うときは「#include <functional>」必須

書き方は「std::function<(戻り値の型<引数の型、引数の型...>) (オブジェクト名)」になる。個人的には関数ポインタよりもわかりやすい気がする。こっちのほうが使い慣れてるからかもしれない(笑)

関数ポインタと同じで、戻り値の型と引数の型と個数が一致していないと代入できない

ちなみに、関数ポインタではラムダ式は代入できない。これは大きなポイントだと思う

 

自分が今回悩んだのは、クラスのメンバ関数の中でstd::functionに同じクラスの別のメンバ関数のアドレスを代入しようと思ったときである

素直に関数アドレスを入れるとエラーになる。これがどうしてエラーになるのかはわからない……

これでしばらく悩んでいたけど、解決方法が判明した

最初にラムダ式で包む方法を思いついて、やってみたらできた。でもわざわざラムダ式で包むのは煩わしいし、なんか違う気がすると思った

bindの方法はTwitterで友だちからアドバイスをもらったので、調べてみたらできた。個人的にはこっちのほうがしっくり来たので、こっちのほうを採用した

 

std::functionを知ってると便利なことがたくさんあるので、もし使う機会があれば使ってみるといいと思う