std::reference_wrapper不能很好地使用std::bind

std::reference_wrapper does not work nicely with std::bind

本文关键字:std bind 不能 reference wrapper 很好      更新时间:2023-10-16

我正在尝试用std::bind模拟C++11 lambdas中的完美/移动捕获。在下面的函数中,我想通过左值或右值传递具有可变"operator()"的处理程序,根据需要复制或移动它并调用它。

template <typename Handler>
void foo (Handler&& h)
{
    std::bind (
        [] (Handler& h) { h (); },
        std::forward<Handler> (h)
    ) ();
}

在大多数情况下,此代码运行良好,但当我使用std::ref包装处理程序时失败。http://coliru.stacked-crooked.com/a/b9c29b6ed6fb5aa8

int main ()
{
    int i = 0;
    auto x = [i] () mutable { std::cout << "i=" << ++i << "n"; };
    foo (x);                // OK
    foo (std::move (x));    // OK
    foo (std::ref (x));     // Error
    return 0;
}

如果我创建自己的"reference_wrapper"实现,它就可以正常工作。http://coliru.stacked-crooked.com/a/6b302233ab86d9ad:

template <typename T>
struct my_reference_wrapper
{
    T& t;
    template <typename ...As> auto
    operator() (As&&... args) const -> decltype (t (std::forward<As> (args)...))
    {
        return t (std::forward<As> (args)...);
    }
};
template <typename T> inline my_reference_wrapper<T>
my_ref (T& t) { return { t }; }
int main ()
{
    int i = 0;
    auto x = [i] () mutable { std::cout << "i=" << ++i << "n"; };
    foo (my_ref (x));     // Now OK
    foo (my_ref (x));     // And even increments 'i' properly.
    return 0;
}

是std::bind错误吗?

有没有可能让它用c++11编译,只使用std库类,而不重新设计自己的包装器?

std::bindstd::reference_wrapper有特殊处理。

您可以添加过载来处理:

template <typename T>
void foo (std::reference_wrapper<T> h)
{
    std::bind ([] (T& t) { t(); }, h) ();
}

演示