組み込みでラムダは使って良いけど、std::functionは駄目っぽい2019-09-10組み込みでラムダは使って良いけど、std::functionは駄目っぽいC/C++例えば、組み込みでウォッチドックタイマー(WDT)を使う場面を想定しましょう。}}無茶苦茶長い処理をする場合は処理中にクリアを挟むことはあるだろうけど、基本形はこれでいいでしょう。?なんとも思わない?よし、君は素晴らしい人格者だ。さぁ、無駄な時間を過ごす前に、ブラウザバックするなり、タブを今すぐ閉じるんだ。した何かを感じるかい?奇遇だ、私もだ。さぁ、私と一緒に地獄に堕ちようよ。書きたいさて、上記の様なコードを見ると、私としては、例えばこう書きたくなります。});}クリアだなのなんだのは隠蔽して、勝手にやって欲しい。一回のループでするべき処理だけ定義して、後は自動でやって欲しいのです。処理の「意味」だけに注力したいのです。レジスタとか後から読んで読めないゴミクズを、一々触りたくないのです。(なお、1msはstd::chrono_literalsに定義してあります。ユーザー定義リテラルで自作できます。)std::functionで関数を渡すこのように、何か勝手にやって欲しい処理の間に、ユーザー定義の処理を挟むには大凡以下の方法があります。関数を定義して、関数ポインタを渡す関数オブジェクトを渡すラムダ式を渡す先に書いた例ではラムダ式を使っていますね。実際にはラムダ式は2の糖衣構文なので、基本的には二つですね。「C++は関数ポインタよりも、関数オブジェクトの方が最適化が効きやすい」という話もありますが、最近のコンパイラは賢いので、関数ポインタでも最適化がいけてる気がします。実際、手元にあるIARのコンパイラでリリースビルドすると、関数ポインタの最適化ができています。どれを使うにせよ、受け取る側(loopメソッド)はC++11以上では、std::functionで簡単に同じように受け取ることができます。func);これをビルドするとどうなるのでしょうか?以降はWDTの例を引きずるとコードが長くなるので、以下の様な単純なコードで考えてみましょう。});}IARのコンパイラで上記のコードをデバッグビルドすると、マップファイルは以下の様になります。[1](略)newとかdeleteとかallocatorとか、組み込みの敵なメソッドがずらり。最適化してないからしょうが無いのかと思ったら、リリースビルドにしても、deleteや仮想テーブルが残る結果になりました。これでは、組み込み的にはちょっと使えません。ARM8.40のコンパイラでは消えませんでした。そこで、もうちょっと最適化させやすくしてみます。f)fooにinlineを付けてみました。これでリリースビルドをすると、デリータ関連が消えました。fooも消えたので、fooがinline展開されて、デリータがいらなくなったのでしょう。(というか、C++において、inlineは基本的にヘッダーに関数をかける以上の意味は無いと思っていたのですが、消えてびっくり)しかし、仮想テーブルは残りました。std::functionという情報を消せてないようですね。(無論コンパイラによっても違うでしょうが)ということは、どうも組み込み的にはstd::functionが敵のようです。君もstd::vectorとかと同類の禁止薬物だったか。sdt::functionを使わず、templateにしてみるfunctionがだめならば、使わなければいいのだろう?と単純にtemplate化してみました。f)これを、デバッグビルドしたときのマップファイルが以下です。1)]という型の関数オブジェクトになったお陰で、デバッグビルドだというのに、newだとかallocとかdeleteとか仮想テーブルが一切なくなっています。ちなみに、最適化すると、fooもラムダ式もインライン展開されて、全部消えてました。これなら、組み込みでもニッコリですね。関数ポインタテンプレートでもニッコリですが、関数ポインタにもしてみましょう。例の様に、キャプチャしていないラムダ式は関数ポインタに暗黙に変換できます。0;}これを同様にIARでデバッグビルドするとこんなんができてて、微妙に8byteほどサイズが大きい。[1]この_FUNってなんじゃらほい?というわけで、逆アセンブル。PC}単にインスタンスを置いてラムダ式をコールしてreturnしてるだけですね。暗黙変換されるとき、こいつが渡されるようです。いう処理が入る分、8byteほどデバッグビルドのサイズが大きくなった様子。最適するとどっちも同じ結果になりました。まとめ組み込みにおいては、肥大化しても良いならテンプレートを、そうでないなら関数ポインタを使いましょう。近年のコンパイラは賢いので、関数ポインタでもちゃんと最適化してくれます。これは2019年現在の話であって、コンパイラが賢くなれば、std::functionでも良くなるかも知れませんが。00:50関連記事2019-06-03組み込み屋こそC++を使うべきなのですやーやーやー。なんで私、最近こんな黒魔術に手を出してるんだろ...2018-02-01WindowsでVerilatorをインストール(MSYS2)VerilatorとはVerilogコードをシミュレーション可能なC++コード...2016-11-30jshellを自分のプログラムに組み込みたかったはい。しょーもないことしてました。»プロフィールJavaで画像AI屋だったハズが、気がついたら制御論理やってて、Eclipse開発してて、組み込み屋で、CortexM4周りの開発してて、VerilogでRTL書いてて、STAしてて、色んな小さいインフラ管理してる、何でも屋。働きたくないでござる。(14)スターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。