std::bind
предназначен для частичного применения .
То есть предположим, что у вас есть объект-функция, f
который принимает 3 аргумента:
f(a,b,c);
Вам нужен новый объект функции, который принимает только два аргумента, определенных как:
g(a,b) := f(a, 4, b);
g
является «частичным применением» функции f
: средний аргумент уже указан, и осталось два.
Вы можете использовать std::bind
для получения g
:
auto g = bind(f, _1, 4, _2);
Это более лаконично, чем написание класса функторов для этого.
В статье, на которую вы ссылаетесь, есть другие примеры. Обычно вы используете его, когда вам нужно передать функтор некоторому алгоритму. У вас есть функция или функтор, которые почти выполняют ту работу, которую вы хотите, но более настраиваемую (т. Е. Имеют больше параметров), чем использует алгоритм. Таким образом, вы привязываете аргументы к некоторым параметрам, а остальное оставляете алгоритму для заполнения:
// raise every value in vec to the power of 7
std::transform(vec.begin(), vec.end(), some_output, std::bind(std::pow, _1, 7));
Здесь pow
принимает два параметра и может возводиться в любую степень, но все, что нас волнует, - это возведение в степень 7.
В качестве случайного использования, которое не является частичным приложением функции, bind
также можно изменить порядок аргументов функции:
auto memcpy_with_the_parameters_in_the_right_flipping_order = bind(memcpy, _2, _1, _3);
Я не рекомендую использовать его только потому, что вам не нравится API, но он имеет потенциальное практическое применение, например, потому что:
not2(bind(less<T>, _2, _1));
является функцией «меньше или равно» (при условии полного порядка, бла-бла). В этом примере обычно нет необходимости, поскольку уже существует std::less_equal
(он использует <=
оператор вместо <
, поэтому, если они не согласованы, вам может понадобиться это, и вам также может потребоваться посетить автора класса с подсказкой). Однако это своего рода трансформация, которая возникает, если вы используете функциональный стиль программирования.
myThread=boost::thread(boost::bind(&MyClass::threadMain, this))
std::function
?pow
пример не компилируется. Посколькуpow
это перегруженная функция, вам необходимо вручную указать, какая именно перегрузка. Привязка не может оставлять это на усмотрение вызывающей стороны результирующего функтора. Напр.std::transform(vec.begin(), vec.end(), out.begin(), std::bind((double (*)(double, int))std::pow, _1, 7));
std::bind
приходит вместе сthis
использованием в качестве 2 - го аргумента. Не могли бы вы уточнить этот вариант использования?std::placeholders::_1
. Мне потребовалось время, чтобы выяснить, почему это не компилируется.Одно из основных применений std :: function и std :: bind - это более генерализованные указатели на функции. Вы можете использовать его для реализации механизма обратного вызова. Один из популярных сценариев заключается в том, что у вас есть функция, выполнение которой займет много времени, но вы не хотите ждать, пока она вернется, тогда вы можете запустить эту функцию в отдельном потоке и дать ей указатель на функцию, которая будет обратный вызов после его завершения.
Вот пример кода, как это использовать:
источник
std :: bind был включен в библиотеку после предложения включить привязку ускорения, в первую очередь это частичная специализация функций, в которой вы можете исправить несколько параметров и изменить другие на лету. Теперь это библиотечный способ выполнения лямбда-выражений в C ++. Как ответил Стив Джессоп
Теперь, когда C ++ 11 поддерживает лямбда-функции, я больше не чувствую соблазна использовать std :: bind. Я бы предпочел каррирование (частичную специализацию) с функцией языка, чем с функцией библиотеки.
Объекты std :: function являются полиморфными функциями. Основная идея состоит в том, чтобы иметь возможность ссылаться на все вызываемые объекты взаимозаменяемо.
Для получения более подробной информации я хотел бы указать вам на эти две ссылки:
Лямбда-функции в C ++ 11: http://www.nullptr.me/2011/10/12/c11-lambda-having-fun-with-brackets/#.UJmXu8XA9Z8
Вызываемая сущность в C ++: http://www.nullptr.me/2011/05/31/callable-entity/#.UJmXuMXA9Z8
источник
std::bind
никогда не существовал без лямбда-выражений - обе эти функции были введены в C ++ 11. У нас былиbind1st
иbind2nd
которые были изможденными версиями связывания C ++ 11.Я использовал его давно, чтобы создать пул потоков плагинов на C ++; Поскольку функция принимала три параметра, вы можете написать так
Предположим, у вашего метода есть подпись:
Чтобы создать функциональный объект для привязки трех параметров, вы можете сделать это следующим образом
Теперь, чтобы связать параметры, мы должны написать функцию связывания. Итак, вот оно:
И вспомогательная функция для использования класса binder3 - bind3:
и здесь мы, как это назвать
Примечание: f3 (); вызовет метод task1-> ThreeParameterTask (21,22,23);
Для более подробных подробностей -> http://www.codeproject.com/Articles/26078/AC-Plug-in-ThreadPool-Design
источник