std::reference_wrapper与std::bind不兼容。

4

我想使用std::bind在C++11 lambda中模拟完美/移动捕获。 在下面的函数中,我希望通过lvalue或rvalue传递可变的“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;
}

如果我创建自己的“引用包装器”实现,它可以正常工作。 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的一个bug吗?

是否可能只使用std库类,在使用c++11编译时使其编译,而不需要重新发明自己的包装器?

1个回答

3

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

您可以添加重载来处理它:

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

演示


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接