gpt4 book ai didi

c++ - 在可变参数模板中使用 std::bind 完美转发引用

转载 作者:行者123 更新时间:2023-11-30 03:28:28 24 4
gpt4 key购买 nike

我在我的代码中偶然发现了一个错误,我追查到 std::bind 的参数“... are never passed by reference unless wrapped in std::ref or std::cref”。

我有什么

我有一个看起来像这样的函数模板(去除了不相关的位):

template<typename F, typename ... Args>
auto eval(F&& _f, Args&&... _args)
{
using ret_t = typename std::result_of<F&&(Args&&...)>::type;

std::function<ret_t()> func(std::bind(std::forward<F>(_f), std::forward<Args>(_args)...)));
// Etc.
}

到目前为止一切顺利,但是如果函数 _f 将引用作为参数,这就会崩溃,因为参数被复制或移动,除非包装在 std::ref 中>std::cref

我想要什么

一种将参数作为对 _f 的引用传递同时尽可能保留完美转发的方法。我非常想通过将每个 _args 包装在原点处的 std::ref 中来避免传递每个 _args 。相反,我希望在 eval() 中自动计算出引用。

我尝试过的

binding _args 似乎有效时,使用 std::ref 而不是 std::forward :

template<typename F, typename ... Args>
auto eval(F&& _f, Args&&... _args)
{
using ret_t = typename std::result_of<F&&(Args&&...)>::type;

// Replace std::forward<Args>() with std::ref()
std::function<ret_t()> func(std::bind(std::forward<F>(_f), std::ref(_args)...)));
// Etc.
}

但我不知道这对右值引用有何影响。始终使用 std::ref 是否安全?这是矫枉过正吗?我还有完美转发吗?问题比比皆是。

我也考虑过用通用 lambda 替换 std::bind,但我不确定如何捕获参数以实现完美转发。

如有任何见解,我们将不胜感激。

最佳答案

Is it safe to always use std::ref?

它和正常使用引用一样安全。所以在这种情况下,如果 func 没有超过函数 eval(),那么它就是安全的。即使我传入右值,引用也不会悬空。但是,如果您需要将 func 存储在某处,那么这就是悬挂引用的秘诀。

您想要做的是有条件地将它们包装为引用。一种方法是为左值和右值提供两个重载:

template <class T> std::reference_wrapper<T> maybe_wrap(T& val) { return std::ref(val); }
template <class T> T&& maybe_wrap(T&& val) { return std::forward<T>(val); }

左值变成引用包装器,右值保持为右值引用。现在:

std::function<ret_t()> func(std::bind(std::forward<F>(_f), 
maybe_wrap(std::forward<Args>(_args))...));

是安全的。


请注意,调用绑定(bind)表达式的方式与您确定返回类型的方式并不完全匹配。所有绑定(bind)参数都作为左值传递,因此您真正需要的是:

using ret_t = typename std::result_of<F&(Args&...)>::type;
// ^^^^^^^^^^^

您也可以将其替换为 lambda,这很尴尬,因为捕获参数包的方式有限。您必须通过一个元组并实现 std::apply()(这在 C++14 中是可行的):

[f=std::forward<F>(f),
args=std::make_tuple(std::forward<Args>(_args)...)]() -> decltype(auto)
{
return std::apply(f, args);
}

不过,由于存在必要的障碍,而且无论如何都会被类型删除,也许 bind() 更好。

关于c++ - 在可变参数模板中使用 std::bind 完美转发引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46564845/

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