C++1y no viable conversion from std::bind to std::function

纵然是瞬间 提交于 2019-12-04 22:31:56

INTRODUCTION

std::bind will try to call func1<Handler> with an lvalue-reference, but your instantiation of func1 will make it only accept rvalues.


EXPLANATION

Here we have reduced your testcase to the bare minimum to show what is going on, the snippet below is ill-formed and an explanation will follow to why that is.

#include <functional>

template<class T>
void foobar (T&& val);

int main() {
  std::function<void()> f = std::bind (&foobar<int>, std::move (123));
}

In the above we will instantiate foobar with T = int, which makes the type of argument val to be an rvalue-reference to int (int&&).

std::move(123) will move-construct our value to be stored inside the object created by std::bind, but the Standard says that when std::bind later invokes the stored function, all arguments are passed as TiD cv &; ie. as lvalues.

This behavior is mandated by the Standard (n3797), as stated in section [func.bind.bind]p10.


By changing the previous ill-formed snippet into the following, no error will be raised, since foobar<int> now accepts an lvalue-reference; suitable to be bound to the lvalue passed to our function by the function-object returned by std::bind.

  std::function<void()> f = std::bind (&foobar<int&>, std::move (123));

???

#include <functional>
#include <type_traits>
#include <iostream>

int main() {
  auto is_lvalue = [](auto&& x) {
    return std::is_lvalue_reference<decltype(x)> { };
  };

  auto check = std::bind (is_lvalue, std::move (123));
  bool res   = check (); // res = true
}

in short: function has to be copyable. bind with rvalue returns non-copyable object. Workaround is to capture/bind with shared_ptr containing abovementioned value

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!