19

少し前に、私はstd::functionこのようにかなり使用しました:

std::function<void(int)> func = [](int i) -> int { return i; };

基本的に、さまざまな関数オブジェクトを に格納したかったのでこれを行いましたstd::functionが、これらの関数の戻り値の型を制限したくありませんでした。これはうまくいくように見えたので、私はそれに行きました。しかし、私はそれが安全に使用できると確信しておらず、それに関するドキュメントを見つけることができませんでした. この使用法が正当かどうかは誰にもわかりませんか? または、より一般的には、に安全に割り当てることができるオブジェクトのルールは何std::functionですか?

編集

明確にするために、私が懸念している問題は、ラムダ関数が戻り値の型で宣言されてintいる間、を返すことです。特に呼び出しが行われると、これで問題ないかどうかわかりません。funcvoidfunc()

4

3 に答える 3

21

あなたのコードには未定義の動作があります。期待どおりに動作する場合とそうでない場合があります。動作が定義されていない理由は、20.8.11.2.1 [func.wrap.func.con]/p7 が原因です。

必須: Fである必要がありますCopyConstructible。引数の型と戻り値の型fに対して Callable (20.8.11.2) である必要があります。ArgTypesR

f戻り値の型が Callable であるためにはR、暗黙のうちに戻り値の型(の場合) にf変換可能なものを返さなければなりません。Andは暗黙的に に変換できません。std::functionvoidintvoid

あなたのコードがほとんどの実装で機能することを期待しています。ただし、少なくとも 1 つの実装 ( libc++ ) では、コンパイルに失敗します。

test.cpp:7:30: error: no viable conversion from 'int (int)' to 'std::function<void (int)>'
    std::function<void(int)> ff = f;
                             ^    ~

皮肉なことに、この動作の根拠は別の SO questionに由来します。

もう 1 つの質問では、使用上の問題がありましたstd::function。この問題の解決策には、コンパイル時にRequires:句を強制する実装が含まれていました。対照的に、この質問の問題の解決策は、実装が Requires:句を強制することを禁止することです。

于 2012-02-18T17:27:31.550 に答える
1

ユースケースは、標準に従って明確に定義されています。

std::function呼び出し可能なオブジェクトからを構築しています[1]

§20.8.11.2.1/7:

template<class F> function(F f);

必要なもの:FはCopyConstructibleでなければなりません。fは、引数タイプArgTypesおよび戻りタイプRに対して呼び出し可能(20.8.11.2)でなければなりません。

それで、あなたのfは呼び出し可能ですか?

§20.8.11.2/2は言う:

タイプFの呼び出し可能オブジェクトfは、引数タイプArgTypesに対して呼び出し可能でありINVOKE (f, declval<ArgTypes>()..., R)、未評価のオペランド(節5)と見なされる式が整形式(20.8.2)の場合、タイプRを返します。

そしての定義はINVOKE言う:

§20.8.2

  1. 次のように定義INVOKE (f, t1, t2, ..., tN)します。...メンバー関数/変数ポインタを処理するもの...—f(t1, t2, ..., tN)他のすべての場合。

  2. INVOKE (f, t1, t2, ..., tN, R) as INVOKE (f, t1, t2, ..., tN)暗黙的にに変換されたものを定義しRます。

また、どのタイプも暗黙的にに変換できるためvoid、コードは標準に準拠したコンパイラで問題ないはずです。以下のlitbで指摘されているように、voidへの暗黙の変換はないため、これは明確に定義されていません。

[1]:ラムダはここでは呼び出し可能なオブジェクトとしてカウントされると思いますが、そのためのリファレンスはありません。ラムダはコンテキストをキャプチャしないため、関数ポインタとしても使用できます

于 2012-02-18T12:15:47.430 に答える
0

これは、匿名関数には問題ないようです。

http://www.alorelang.org/release/0.5/doc/std_function.htmlからの引用(これは C++ 標準ライブラリからのものではありませんが、C++ までのバインディングで同様のものを使用しているようです)

関数オブジェクトは、関数定義、無名関数式、またはドット (.) 演算子を使用してバインドされたメソッドにアクセスすることによってのみ作成できます。

これを行う別の方法は、次のように関数ポインタを auto に格納することです: http://en.wikipedia.org/wiki/Anonymous_function (C++ セクション)

于 2012-02-18T08:49:39.463 に答える