c++ - std::reference_wrapper 不能很好地与 std::bind 一起工作

标签 c++ c++11

我正在尝试使用 std::bind 在 C++11 lambda 中模拟完美/移动捕获。在下面的函数中,我想通过左值或右值传递具有可变“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::bindstd::reference_wrapper 有特殊处理.

您可以添加重载来处理:

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

Demo

关于c++ - std::reference_wrapper 不能很好地与 std::bind 一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34344856/

相关文章:

C++ IOS 额外字符

c++ - 如何格式化 std::chrono 持续时间?

c++ - OS-X 支持 std::tr1

c++ - 如果不 make clean,Makefile 不会重新编译

c++ - msys2 下的 gcc 和 clang 无法解析包含绝对路径的内容

c++ - 如何迭代无序映射的特定键的值?

c++ - 深度测试的奇怪结果

c++ - 关于 c++11 中的 std::result_of

c++ - 部分模板类型推导

c++ - return 语句中的统一初始化以及将运算符显式转换为 bool