Как я понимаю,
std::bind
отлично перенаправляет как вызываемый объект, который он обертывает, так и аргументы этому вызываемому объекту;- возвращаемый объект
std::bind
сам является перемещаемым и/или копируемым, в зависимости от того, являются ли вызываемый объект и его аргументы перемещаемыми и/или копируемыми; - возвращаемый объект
std::bind
может быть вложенным, и в этом случае внешний возвращаемый объектstd::bind
можно перемещать и/или копировать, как и при связывании других вызываемых объектов.
Поэтому я ожидаю, что следующий фрагмент кода скомпилируется нормально. Вместо этого код генерирует кучу ошибок компилятора в последних двух операторах в main()
.
#include <functional>
template<typename HandlerType>
void call_handler(HandlerType&& handler)
{
handler();
}
template<typename HandlerType>
void do_something(HandlerType&& handler)
{
auto f = std::bind(
&call_handler<HandlerType&>,
std::forward<HandlerType>(handler));
f();
}
int main()
{
auto a = [&]() {};
do_something(a);
do_something(std::move(a));
auto b = std::bind([&]() {});
do_something(b); // <- compiler error!
do_something(std::move(b)); // <- compiler error!
}
Каждая из двух проблемных строк выдает ошибки без другой. Чтобы устранить все ошибки, я должен закомментировать обе строки.
Вот пример ошибки из g++ 4.9.2 в Cygwin при вызове f()
в do_something()
:
(4 of 103): error: no match for call to ‘(std::_Bind<void (*(std::_Bind<main()::<lambda()>()>))(std::_Bind<main()::<lambda()>()>&)>) ()’
Вот пример ошибки из Visual Studio 2013 в той же строке:
1>C:\Program Files (x86)\Microsoft Visual Studio12.0\VC\include\functional(1149): error C2664: 'void (HandlerType)' : cannot convert argument 1 from 'void' to 'std::_Bind<false,void,main::<lambda_2b8ed726b4f655ffe5747e5b66152230>,> '
Что происходит? Я неправильно понимаю std::bind
?
В частности, как я могу
- привязать вызываемый объект? и
- передать этот возвращаемый объект
std::bind
функции, принимающей универсальную ссылку? и - вложить этот
std::bind
возвращаемый объект в другойstd::bind
?
Моя цель состоит в том, чтобы базовый вызываемый объект и его аргументы были идеально перенаправлены.
EDIT: Чтобы уточнить, я хочу передать обернутый вызываемый объект и его аргументы по значению, а не по ссылке, поэтому std::ref
не поможет — по крайней мере, не как полное решение. Причина в том, что мой реальный код более сложен и включает в себя передачу возвращаемого объекта f
std::bind
через границу потока, а возвращаемые объекты a
и b
std::bind
могут выйти за пределы области действия в исходном потоке до того, как call_handler
вызовет f()
, поэтому a
и b
нужно скопировать или переместить в f
, а не просто ссылки. Тем не менее, мой вопрос конкретно о std::bind
и идеальной пересылке, и для того, чтобы задать хороший вопрос, я выделил все, что не нужно для воспроизведения конкретных ошибок компилятора, о которых я упоминал.