実際には、遅延起動ファンクタ(いくらかstd::bind
のようなものですが、ネストされたバインド式/プレースホルダ機能はありません)を作成する小さなユーティリティを作成しました。私の主な動機は、私が見つけたこのケースだった直感に反する:
using pointer_type = std::unique_ptr<int>;
pointer_type source();
void sink(pointer_type p);
pointer_type p = source();
// Either not valid now or later when calling bound()
// auto bound = std::bind(sink, std::move(p));
auto bound = std::bind(
[](pointer_type& p) { sink(std::move(p)); }
, std::move(p));
bound();
(sink
にその左辺値参照引数を動かす)、そのアダプタの理由はstd::bind
によってコールラッパー・リターンは常に左辺値としてバインドされた引数を転送するということです。これは、例えば、 boost::bind
をC++ 03に置き換えます。そのlvalueは、基本となるCallableオブジェクトの参照引数またはコピーを介した値引数にバインドされるためです。 pointer_type
は移動のみのため、ここでは機能しません。
私が得た洞察力は本当に考慮すべき二つのものがあるということです:バウンド引数はがを保存しなければならない、そしてそれらがどのように(すなわち、Callableオブジェクトに渡された)を復元する必要がありますか。 std::bind
が許可するコントロールは次のとおりです。引数は、浅い(std::ref
を使用して)または通常の方法(完全転送を伴うstd::decay
を使用)に格納されます。それらは常にlvaluesとして復元されます(所有する呼び出しラッパーから継承されたcv修飾子を使用して)。あなたは私がちょうど行ったような小さなオンサイトアダプターのラムダ式で後者をバイパスすることができます。
これはおそらく、学習するのが比較的少ないため、多くの制御と多くの表現があります。比較すると、私のユーティリティはbind(f, p)
(laveueとして復元とストアコピー、復元)、bind(f, ref(p))
(lvalueとして復元する)、bind(f, std::move(p))
(移動からの崩壊と移動、rvalueとして復元)、bind(f, emplace(p))
(移動からの崩壊とストア、左辺値として復元)。これはEDSLの学習に似ています。
ローカルに参照をバインドすると、問題が発生します。 – mfontanini
呼び出された関数がローカルのスコープを超えて存在しない場合は、私はなりません。あなたの足を吹き飛ばすことができる多くのことがC++にあります。私の質問は、この行動がそれほど直感的ではないように見える点です。 – ryaner
ある時点で、私の答えに「とその地方が範囲外になる」が含まれていましたが、明らかに編集後に消去されてしまいました:S – mfontanini