Когда следует использовать std::bind?

Каждый раз, когда мне нужно использовать std::bind, вместо этого я использую лямбду. Итак, когда я должен использовать std::bind? Я только что закончил удалять его из одной кодовой базы и обнаружил, что лямбды всегда проще и понятнее, чем std::bind. Разве std::bind не является совершенно ненужным? Разве это не должно быть устаревшим в будущем? Когда я должен предпочесть std::bind лямбда-функциям? (Должна быть причина, по которой он попал в стандарт одновременно с лямбда-выражениями.)

Я также заметил, что все больше и больше людей знакомы с лямбда-выражениями (поэтому они знают, что делают лямбда-выражения). Однако гораздо меньше людей знакомы с std::bind и std::placeholders.


person gnzlbg    schedule 24.03.2013    source источник
comment
возможный дубликат Bind Vs Lambda?   -  person Jonathan Wakely    schedule 24.03.2013
comment
См. См. stackoverflow.com/a/17545183/1274850   -  person BertR    schedule 04.09.2017


Ответы (2)


Вот что вы не можете сделать с лямбдой:

std::unique_ptr<SomeType> ptr = ...;
return std::bind(&SomeType::Function, std::move(ptr), _1, _2);

Лямбда-выражения не могут захватывать типы, предназначенные только для перемещения; они могут захватывать значения только путем копирования или ссылки на lvalue. Хотя, по общему признанию, это временная проблема, которая активно решается для С++ 14;)

"Проще и понятнее" - это вопрос мнения. Для простых случаев привязки bind может потребоваться намного меньше ввода. bind также ориентирован исключительно на привязку функций, поэтому, если вы видите std::bind, вы знаете, на что смотрите. В то время как если вы используете лямбду, вам нужно посмотреть на реализацию лямбды, чтобы быть уверенным в том, что она делает.

Наконец, C++ не осуждает вещи только потому, что некоторые другие функции могут делать то же, что и они. auto_ptr устарел, поскольку его использование опасно по своей сути, и существует неопасная альтернатива.

person Nicol Bolas    schedule 24.03.2013
comment
+1. Похоже, что в выходящей книге Скотта Мейерса "Эффективное" есть пункт. C++11: предпочитайте лямбда-выражения std::bind. У меня недостаточно знаний, чтобы прокомментировать это, но если бы вы могли, это было бы здорово. - person Andy Prowl; 24.03.2013
comment
Спасибо за такой отличный ответ! Есть статья о захвате ходом: marcoarena.wordpress.com/2012/11/01/ Надеемся, что в следующем стандарте мы получим настоящий захват за ход. - person gnzlbg; 24.03.2013
comment
C++-14 исправит этот недостаток лямбда-выражений. - person David Schwartz; 04.03.2015
comment
@AndyProwl наиболее применима эта краткая цитата из книги, которую вы цитируете: ... начиная с C++ 14, просто нет хороших вариантов использования для [std::bind] - person Drew Dormann; 06.03.2015
comment
Хотя я думаю, что с С++ 14 вы, вероятно, можете полностью заменить std::bind лямбда-выражениями (и я в основном так и делаю), мне все же нравится ваша точка зрения о том, что std::bind менее мощный и, таким образом, более четко излагает намерение. - person MikeMB; 16.03.2015

Вы можете создавать полиморфные объекты с помощью std::bind, чего нельзя сделать с помощью лямбда-выражений, т. е. оболочку вызова, возвращаемую std::bind, можно вызывать с различными типами аргументов:

#include <functional>
#include <string>
#include <iostream>

struct Polly
{
  template<typename T, typename U>
    auto operator()(T t, U u) const -> decltype(t + u)
    { return t + u; }
};

int main()
{
  auto polly = std::bind(Polly(), std::placeholders::_1, "confusing");

  std::cout << polly(4) << polly(std::string(" this is ")) << std::endl;    
}

Я создал это как головоломку, не являющуюся примером хорошего кода, но демонстрирующую полиморфные оболочки вызовов.

person Jonathan Wakely    schedule 24.03.2013
comment
Да, в C++14 это эквивалентно выражению привязки: [p = Polly{}](auto t) { return p(t, "confusing"); } - person Jonathan Wakely; 28.11.2014
comment
@Elliot Polly operator() явно константа, поэтому я не знаю, что вы имеете в виду. Код в вопросе компилируется нормально, как и лямбда-выражение в моем первом комментарии выше. - person Jonathan Wakely; 02.09.2020
comment
Извинения. Я тупо пропустил const. «Надо было приглядеться, прежде чем комментировать. - person Elliott; 03.09.2020