繁体   English   中英

std :: bind和rvalue引用

[英]std::bind and rvalue reference

让我们考虑以下代码:

class Widget{
};

int main(){
Widget w;
auto lambda = bind([](Widget&& ref){ return; }, std::move(w));

return 0;
}

它会触发错误

no match for call to ‘(std::_Bind<main()::<lambda(Widget&&)>(Widget)>) ()’
     lambda();

我的问题是:为什么错误出现了? 毕竟,我对rvalue引用进行了显式转换 - 我的意思是std::move(w) ,我通过rvalue引用参数 - 我的意思是Widget&& ref

这是怎么回事?

而且下面的代码有效,让我更担心的是:

class Widget{
};

int main(){
Widget w;
auto lambda = bind([](Widget& ref){ return; }, std::move(w));

return 0;
}

如果你写下std::bind示意图,可能会更清楚。

// C++14, you'll have to write a lot of boilerplate code for C++11
template <typename FuncT, typename ArgT>
auto
bind(FuncT&& func, ArgT&& arg)
{
  return
    [
      f = std::forward<FuncT>(func),
      a = std::forward<ArgT>(arg)
    ]() mutable { return f(a); };  // NB: a is an lvalue here
}

由于你可以多次调用函数对象std::bind ,它不能“使用”捕获的参数,因此它将作为左值引用传递。 bind本身作为rvalue传递的事实意味着在初始化a的行上没有复制。

如果您尝试使用上面显示的原理图bind编译示例,您还将从编译器中获得更有用的错误消息。

main.cxx: In instantiation of ‘bind(FuncT&&, ArgT&&)::<lambda()> mutable [with FuncT = main()::<lambda(Widget&&)>; ArgT = Widget]’:
main.cxx:10:33:   required from ‘struct bind(FuncT&&, ArgT&&) [with FuncT = main()::<lambda(Widget&&)>; ArgT = Widget]::<lambda()>’
main.cxx:11:31:   required from ‘auto bind(FuncT&&, ArgT&&) [with FuncT = main()::<lambda(Widget&&)>; ArgT = Widget]’
main.cxx:18:59:   required from here
main.cxx:11:26: error: no match for call to ‘(main()::<lambda(Widget&&)>) (Widget&)’
    ]() mutable { return f(a); };  // NB: a is an lvalue here
                          ^
main.cxx:11:26: note: candidate: void (*)(Widget&&) <conversion>
main.cxx:11:26: note:   conversion of argument 2 would be ill-formed:
main.cxx:11:26: error: cannot bind ‘Widget’ lvalue to ‘Widget&&’
main.cxx:18:33: note: candidate: main()::<lambda(Widget&&)> <near match>
   auto lambda = bind([](Widget&&){ return; }, std::move(w));
                                 ^
main.cxx:18:33: note:   conversion of argument 1 would be ill-formed:
main.cxx:11:26: error: cannot bind ‘Widget’ lvalue to ‘Widget&&’
    ]() mutable { return f(a); };  // NB: a is an lvalue here

为了使它工作,你需要像这样写:

#include <functional>
#include <iostream>

class Widget{};

int main()
{
    Widget a;
    auto lf = [](Widget&& par){ };

    auto f = std::bind
    (
        lf,
        std::bind
        (
            std::move<Widget&>, a
        )
    );
    f();
    return 0;
}

我的编译器是gcc version 4.9.2 20141101 (Red Hat 4.9.2-1) (GCC)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM