R()
- likeをvoid()
- like呼び出し可能オブジェクトに変換する次のコードを思いつきました。
#include <utility>
template<class Callable>
auto discardable(Callable&& callable)
{ return [&]() { (void) std::forward<Callable>(callable)(); }; }
// ^-- is it ok?
int main()
{
auto f = discardable([n=42]() mutable { return n--; });
f();
}
参考までに攻略について心配です。
callable
が決してコピーされず、存続期間が終了した後に使用されないことを保証しますか?これはC++ 14とタグ付けされていますが、以下のすべての標準に適用されます。
ラムダはoperator()
を持つ匿名の構造体です。キャプチャリストはそのメンバーのタイプを指定するための特別な方法です。参照によるキャプチャーは、実際にはそれがどのように聞こえるかということです。参照メンバーがいます。参照先をぶら下げるのは難しくありません。
これは、具体的にしないでください完全に転送したい場合です。引数が左辺値か右辺値の参照かによって、セマンティクスは異なります。
template<class Callable>
auto discardable(Callable& callable)
{
return [&]() mutable { (void) callable(); };
}
template<class Callable>
auto discardable(Callable&& callable)
{
return [callable = std::forward<Callable>(callable)]() mutable { // move, don't copy
(void) std::move(callable)(); // If you want rvalue semantics
};
}
callable
はxvalueである可能性があるため、ラムダキャプチャの前に破壊される可能性があり、キャプチャ内にぶら下がっている参照が残ります。これを防ぐには、引数がr値の場合、コピーする必要があります。
実際の例:
_template<class Callable>
auto discardable(Callable&& callable) { // This one makes a copy of the temporary.
return [callable = std::move(callable)]() mutable {
static_cast<void>(static_cast<Callable&&>(callable)());
};
}
template<class Callable>
auto discardable(Callable& callable) {
return [&callable]() mutable {
static_cast<void>(callable());
};
}
_
callable
がl値参照の場合でも、存続期間の問題に直面する可能性がありますが、その存続期間のスコープは、discardable
によって返されるラムダキャプチャのそれよりも小さくなります。したがって、callable
を常に移動またはコピーするのが最も安全で簡単です。
補足として、- _std::apply
_ 、 標準ライブラリアルゴリズム のように、関数オブジェクトの値カテゴリを完全に転送する新しい特殊なユーティリティが常にあります関数オブジェクトを値で受け入れる。つまり、operator()()&
とoperator()()&&
の両方をオーバーロードした場合、標準ライブラリは常にoperator()()&
を使用します。
キャプチャされたラムダのぶら下がり参照を使用するため、プログラムはUBです。
したがって、 ラムダでの完全なフォワードキャプチャ を使用するには、
template<class Callable>
auto discardable(Callable&& callable)
{
return [f = std::conditional_t<
std::is_lvalue_reference<Callable>::value,
std::reference_wrapper<std::remove_reference_t<Callable>>,
Callable>{std::forward<Callable>(callable)}]
{
std::forward<Callable>(f)();
};
}
一時的なラムダを移動構築します。