C++14 lambda - 按引用或值有条件地捕获
C++14 Lambda - Conditionally Capture by Reference or Value
是否可以根据编译时信息有条件地选择 lambda 的捕获方法? 例如。。。
auto monad = [](auto && captive) {
return [(?)captive = std::forward<decltype(captive)>(captive)](auto && a) {
return 1;
};
};
如果decltype(captive)
是std::reference_wrapper
,我希望通过引用捕获,而其他所有内容都由值捕获。
Lambda 捕获类型不能由依赖于模板的名称控制。
但是,您可以通过将创建内部 lambda 委托给重载函数来实现所需的效果:
template<class T>
auto make_monad(T&& arg) {
return [captive = std::forward<T>(arg)](auto&& a) {
std::cout << __PRETTY_FUNCTION__ << " " << a << 'n';
return 1;
};
}
template<class T>
auto make_monad(std::reference_wrapper<T> arg) {
return [&captive = static_cast<T&>(arg)](auto&& a) {
std::cout << __PRETTY_FUNCTION__ << " " << a << 'n';
return 1;
};
}
int main() {
auto monad = [](auto&& captive) {
return make_monad(std::forward<decltype(captive)>(captive));
};
int n = 1;
monad(1)(1);
monad(n)(2);
monad(std::ref(n))(3);
}
输出:
make_monad(T&&)::<lambda(auto:1&&)> [with auto:1 = int; T = int] 1
make_monad(T&&)::<lambda(auto:1&&)> [with auto:1 = int; T = int&] 2
make_monad(std::reference_wrapper<_Tp>)::<lambda(auto:2&&)> [with auto:2 = int; T = int] 3
我不想通过引用捕获reference_wrapper,我想通过引用捕获它所包含的引用。引用包装器最好像引用一样,但由于调用运算符(又名"."运算符)不能重载,因此它在一天结束时会非常惨败。
在这种情况下,您无需更改 std::reference_wrapper<T>
的捕获类型。相反,您可能希望像任何其他类型的参数一样按值捕获它,并在使用站点首先解开参数的包装:
template<class T> T& unwrap(T& t) { return t; }
template<class T> T& unwrap(std::reference_wrapper<T> t) { return t; }
auto monad = [](auto && captive) {
return [captive](auto && a) { // <--- Capture by value.
auto& captive_ref = unwrap(captive); // <--- Unwrap before usage.
return 1;
};
};
它没有回答你的问题,而是你的评论,如何使用operator .
:
您可以添加这两个重载:
template <typename T>
T& get_reference_object(T&& t) { return t; }
template <typename T>
T& get_reference_object(std::reference_wrapper<T> t) { return t.get(); }
然后您可以在 lambda 中使用get_reference_object(arg).foo
:
auto monad = [](auto && captive) {
return [captive = captive](auto&& a) { return get_reference_object(captive).foo(a); };
};
活生生的例子。
相关文章:
- 如何使用 soong 命名空间来有条件地编译模块
- 有条件地将默认参数传递给函数(使用"?"运算符)
- 根据模板类型有条件地删除变量
- 有条件地选择带有 decltype() 和三元运算符的类型
- 如何使用 SFINAE 在方法调用中有条件地定义变量?
- 有条件的打印和计数在 std::map 上有限制
- 如何在 c++ 中有条件地包含标头?
- 如何仅在Qt是用ltcg构建时才有条件地启用ltcg?
- 如何在Visual Studio 2019中有条件地编译c++源文件
- C++可以有条件地向下转换类指针吗
- 使用 SFINAE 有条件地解析分配器成员
- 有条件地删除宏
- 有条件地包含C++标准库
- 如何有条件地将元素添加到 std::array - C++11
- 是否根据编译器版本有条件地包含源文件
- 有条件地启用类C++构造函数
- 我可以有条件地使用多个参数吗?
- 有条件地使用 Boost Python 添加模块
- 有什么东西阻止std::optional::value_or()有条件地不例外吗?
- C++14 lambda - 按引用或值有条件地捕获