gpt4 book ai didi

c++ - 以 lambda 作为参数的约定

转载 作者:行者123 更新时间:2023-12-02 11:25:30 25 4
gpt4 key购买 nike

我正在编写一个 C++ 应用程序,并通过 lambda 参数抽象了一个方法。我最初使用以下签名:

void atomically(void (*block)(T& value, bool& retry))

但我发现您不能将任意 lambda 作为函数指针传递 - lambda 必须没有捕获。我可以使用

void atomically(const std::function<void (T&, bool&)>& block)

除了这部分代码中非常重要的一点是,我们避免在堆上分配,并且创建一个 std::function 可能会分配。 (是否能保证是否/何时发生?)

最后,我可以使用:

template<class F>
void atomically(const F& block) {
// use block() as if it had been declared as above
}

但我发现这是 Not Acceptable ,因为它允许 block 通过值而不是引用来获取其参数,这将是一个很容易犯的错误,并且调试起来非常微妙。

将 lambda 作为参数的正确约定是什么?或者,在最终的模板解决方案中,有没有办法确保 block 通过引用获取其参数?

最佳答案

您可能需要一些 function_view (取自 vittorioromeo )(顾名思义,没有所有权,所以不要存储它):

template <typename TSignature>
class function_view;

template <typename TReturn, typename... TArgs>
class function_view<TReturn(TArgs...)> final
{
private:
using signature_type = TReturn(void*, TArgs...);

void* _ptr;
TReturn (*_erased_fn)(void*, TArgs...);

public:
template <typename T, typename = std::enable_if_t<
std::is_callable<T&(TArgs...)>{} &&
!std::is_same<std::decay_t<T>, function_view>{}>>
function_view(T&& x) noexcept : _ptr{(void*)std::addressof(x)}
{
_erased_fn = [](void* ptr, TArgs... xs) -> TReturn {
return (*reinterpret_cast<std::add_pointer_t<T>>(ptr))(
std::forward<TArgs>(xs)...);
};
}

decltype(auto) operator()(TArgs... xs) const
noexcept(noexcept(_erased_fn(_ptr, std::forward<TArgs>(xs)...)))
{
return _erased_fn(_ptr, std::forward<TArgs>(xs)...);
}
};

那么你可以使用:

void atomically(const function_view<void (T&, bool&)>& block)

关于c++ - 以 lambda 作为参数的约定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59415261/

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