Я провел несколько тестов, используя этот меньший пример, который демонстрирует то же поведение, что и вы:
#include <functional>
#include <iostream>
#include <string>
using std::string;
void print(string s1, string s2)
{
std::cout << s1 << s2 << '\n';
}
int main()
{
using namespace std::placeholders;
typedef std::function< void(string) > fn_t;
fn_t func = std::bind(print, _1, _1);
std::string foo("foo");
func(foo);
}
// outputs: foo
Обратите внимание, что я определил строковый объект с именем "foo" вместо использования строковых литералов. Поведение такое же, поэтому проблема не связана с этим.
Я думаю, что проблема в вашем typedef. Возвращаемое значение bind
(которое не определено) приводится к функции, принимающей string
по значению , в то время как оболочка, возвращаемая bind, вероятно, принимает свои аргументы по rvalue-reference и прекрасно их пересылает. Вместо использования собственного typedef, вы должны использовать ключевое слово auto
, чтобы компилятор автоматически определял тип func
. Если мы изменим основную часть следующим образом, мы получим ожидаемое поведение:
int main()
{
using namespace std::placeholders;
auto func = std::bind(print, _1, _1);
std::string foo("foo");
func(foo);
}
// outputs: foofoo
Другое решение состоит в том, чтобы заменить ваш typedef так, чтобы func
принимал его параметр ссылкой на const:
typedef std::function< void(string const &) > fn_t;
Я не очень понимаю, почему другой typedef не работает ... Предположительно, строка перемещается, как заметил @ipc, но я не знаю, в какой момент выполнения это происходит. Я даже не уверен, что это стандартное поведение, поскольку и function
, и обертка, возвращаемая bind
, должны использовать идеальную пересылку. Возможно, GCC включает в себя некоторые оптимизации, которые перемещают аргументы-оболочки, когда они передаются по значению?
Редактировать
Я провел несколько тестов, оказалось, что реализация GCC std::function
выполняет перемещение своих аргументов, в то время как оболочка, возвращаемая std::bind
, не делает. Я до сих пор не знаю, является ли это стандартом, я собираюсь написать вопрос об этом.