[解決済み] std::function vs テンプレート
質問
C++11のおかげで、私たちは
std::function
ファンクタラッパーのファミリーです。残念なことに、これらの新しい追加機能については、悪い話ばかりが聞こえてくる。一番多いのは、恐ろしく遅いというものだ。私もテストしましたが、テンプレートと比較すると本当にひどいものでした。
#include <iostream>
#include <functional>
#include <string>
#include <chrono>
template <typename F>
float calc1(F f) { return -1.0f * f(3.3f) + 666.0f; }
float calc2(std::function<float(float)> f) { return -1.0f * f(3.3f) + 666.0f; }
int main() {
using namespace std::chrono;
const auto tp1 = system_clock::now();
for (int i = 0; i < 1e8; ++i) {
calc1([](float arg){ return arg * 0.5f; });
}
const auto tp2 = high_resolution_clock::now();
const auto d = duration_cast<milliseconds>(tp2 - tp1);
std::cout << d.count() << std::endl;
return 0;
}
111msに対して1241ms。これは、テンプレートはきれいにインライン化できるのに対して
function
は仮想呼び出しで内部をカバーする。
もちろん、テンプレートには問題があると思います。
- はヘッダーとして提供されなければなりません。これは、ライブラリをクローズドコードとしてリリースする際にやりたくないことかもしれません。
-
を使用しない限り、コンパイル時間が長くなる可能性があります。
extern template
-のようなポリシーが導入されています。 - テンプレートの要件(概念、誰か?)を表現するきれいな方法は(少なくとも私には)ありません。
したがって、次のように仮定してよいでしょうか。
function
として使用することができます。
デファクト
ファンクタを渡す標準的な方法と、高いパフォーマンスを期待する場所にはテンプレートを使うべき?
編集する。
コンパイラはVisual Studio 2012です。 なし CTPです。
解決方法は?
一般的に
デザイン
選択できる状況
テンプレートを使用する
. という言葉を強調しました。
デザイン
のユースケースを区別して考える必要があると思うからです。
std::function
とテンプレートはかなり違います。
一般に、テンプレートの選択は、より広い原則の一例に過ぎません。 コンパイル時にできるだけ多くの制約を指定する。 . その理由は簡単で、プログラムが生成される前にエラーや型の不一致を検出できれば、バグだらけのプログラムを顧客に出荷することはなくなるからです。
さらに、ご指摘の通り、テンプレート関数の呼び出しは静的に(つまりコンパイル時に)解決されますので、コンパイラはコードを最適化し、場合によってはインライン化するために必要なすべての情報を持っています(呼び出しがvtableを介して行われた場合は不可能です)。
確かにテンプレートのサポートは完璧ではありませんし、C++11 ではまだ概念のサポートが不足しています。
std::function
は、その点であなたを救うでしょう。
std::function
はテンプレートの代替ではなく、テンプレートが使用できないデザイン状況のためのツールです。
そのようなユースケースの1つは、次のような呼び出しを解決する必要がある場合です。 実行時 特定のシグネチャに従った callable オブジェクトを呼び出すことで、コンパイル時にその具象型が不明であることを示します。 これは、典型的には、潜在的に 異なる型 が必要です。 一律に呼び出す 登録されたコールバックの種類と数は、プログラムの状態とアプリケーションロジックに基づいてランタイムに決定されます。登録されたコールバックの種類と数は、プログラムの状態とアプリケーションロジックに基づいて実行時に決定されます。これらのコールバックは、ファンクタであったり、普通の関数であったり、特定の引数に他の関数をバインドした結果であったりします。
std::function
と
std::bind
を有効にするための自然なイディオムも提供します。
関数型プログラミング
C++では、関数はオブジェクトとして扱われ、他の関数を生成するために自然にキュレーションされ、結合されます。このような組み合わせはテンプレートでも可能ですが、通常、実行時に結合された呼び出し可能なオブジェクトの型を決定する必要があるユースケースで、同様の設計状況が発生します。
最後に、他の状況として
std::function
は避けられないものです。
再帰的ラムダ
しかし、これらの制限は、概念的な区別というよりも、技術的な制限によって決定されるものだと私は考えています。
まとめますと。 デザイン重視 そして、この2つの構成要素の概念的な使用例が何であるかを理解するように努めてください。もし、あなたが行ったような方法でこの2つを比較するのであれば、あなたはこの2つを、おそらく属していない領域に押し込んでいることになります。
関連
-
[解決済み] テスト
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】リンカーエラーです。"リンカ入力ファイルはリンクが行われていないため未使用"、そのファイル内の関数への未定義参照
-
[解決済み】VC++の致命的なエラーLNK1168:書き込みのためにfilename.exeを開くことができません。
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み] using namespace std;」はなぜバッドプラクティスだと言われるのですか?
-
[解決済み] template "と "typename "キーワードはどこに、なぜ入れなければならないのですか?
-
[解決済み] std::move()とは何ですか?また、どのような場合に使用するのですか?
-
[解決済み] const std::string & をパラメータとして渡す時代は終わったのでしょうか?
-
[解決済み] C++テンプレート関数定義の.CPPファイルへの格納
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Visual Studio 2015で「非標準の構文。'&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み] string does not name a type Errorが発生するのはなぜですか?
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】クラスのコンストラクタへの未定義参照、.cppファイルの修正も含む
-
[解決済み】'std::cout'への未定義の参照
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない
-
[解決済み】c++で.txtファイルから2次元の配列に読み込む
-
[解決済み] C++11の再帰的ラムダ関数
-
[解決済み] フリー関数が期待されるメンバ関数を渡すにはどうしたらよいですか?
-
[解決済み] なぜラムダはプレーンな関数よりもコンパイラによって最適化できるのですか?