♻️
C++ ラムダでPerfect Forwardキャプチャする方法メモ
ラムダの初期化キャプチャで Perfect Forward しようとして以下の様にしてしまうとバグる
template <class T>
auto get_printer(T &&val) {
return [val = std::forward<T>(val)]() {
std::cout << val << std::endl;
};
}
int a = 10;
auto printer = get_printer(a);
printer(); // 10
a = 20;
printer(); // 20 じゃなくて 10 が表示されてしまう???
これは T
が左辺値参照型の時に参照キャプチャじゃなくコピーキャプチャしてしまってるのが問題
なので T
が左辺値参照型の時は reference_wrapper
で、その他の時は move
してキャプチャするみたいなことが必要になる
で、そういう事をちゃんとしようとすると非常にめんどくさそうだが tuple
使えばいい感じにできる
template <class T>
auto get_printer(T &&val) {
return [val = std::tuple<T>(std::forward<T>(val))]() {
std::cout << std::get<0>(val) << std::endl;
};
}
これで左辺値参照の時でも左辺値参照のままキャプチャできるようなる
そして可変長テンプレートにも簡単に対応できる
template <class ...T>
auto get_printer(T &&...val) {
return [val = std::tuple<T...>(std::forward<T>(val)...)]() {
boost::fusion::for_each(val, [](auto &&val) {
std::cout << val << std::endl;
});
};
}
もっと簡単な書き方あったら教えて
C++20 でラムダ式の初期化キャプチャでパック展開できるようになるらしいが結局 forward
するときは使えないのでくそ
Discussion