gpt4 book ai didi

c++ - 在 std::bind 中包装一个 lambda 以捕获 R 值

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:16:10 25 4
gpt4 key购买 nike

我有一种情况,我只能使用 C++11 编译器(gcc 4.7.2,所以我无法访问 C++14 广义 lambda 捕获),所以我使用 std::bind 作为变通方法,如果我需要捕获一个只能移动的对象。

我从 this stackoverflow answer 中了解到该解决方法,并且我使用这种技术取得了很大的成功。

但是,我有一种情况,我通过转发绑定(bind)表达式作为另一个绑定(bind)表达式的绑定(bind)参数来形成高阶仿函数。

我可以简化为一个例子。出于这个问题的目的,该示例是人为设计和简化的:

template <class F>
void func(F&& func)
{
auto f = std::bind(
[](F& f) -> void
{

},
std::forward<F>(func)
);

f(); // causes compiler error
}

int main()
{
func(
std::bind(
[]() { }
)
);
}

由于我无法理解的原因,编译器在我调用 f() 时生成了一大堆错误。我将尝试简化它,而不是粘贴整个错误消息:

test7.cpp:22:2: error: no match for call to ‘(std::_Bind<func(F&&) [with F = std::_Bind<main()::<lambda()>()>]::<lambda(std::_Bind<main()::<lambda()>()>)>(std::_Bind<main()::<lambda()>()>)>) ()’

此错误由 GCC 4.7.2 生成。

我看不出为什么会发生这种情况。在上面人为设计的示例中,您会注意到在 main() 中我有一个围绕空 lambda 的额外 bind 表达式。如果我删除 bind 表达式,并简单地传递空的 lambda,例如:

func([]() { });

...然后没有错误发生。但同样,这是一个人为的示例 - 在实际应用程序中,我需要将 lambda 包装在 bind 表达式中以用于移动捕获。而且我看不出为什么 [](){} 在语义上不同于 std::bind([](){})。它们在功能上应该是等价的,即使它们评估为不同的类型。

那么,为什么会出现这个错误呢?或者这仅仅是 GCC 的问题? (我意识到 4.7.2 在这一点上有点旧。)

最佳答案

bind(f, args...) 的参数之一是调用 bind(g, args...) 的结果时,传递给 f 的参数是评估 g 的结果(参见 [func.bind.bind]/10,特别是项目符号 10.2)。对于您的程序,评估 lambda [](){}结果作为第一个参数传递给 [](F& f) 这当然是错误的。

中等丑陋的解决方案:为隐式转换为引用到包装类型的内部绑定(bind)表达式引入包装类:

template <class F>
class protect_bind_expression {
F f_;
public:
protect_bind_expression(F f) :
f_{std::move(f)} {}

operator F&() { return f_; }
};

template <class F>
protect_bind_expression<typename std::decay<F>::type>
protect(F&& f) {
return {std::forward<F>(f)};
}

template <class F>
void func(F&& func)
{
auto f = std::bind(
[](F&){},
protect(std::forward<F>(func))
);

f(); // Doesn't cause compiler error
}

关于c++ - 在 std::bind 中包装一个 lambda 以捕获 R 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33319616/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com