Кога трябва да използвам 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);

Lambda не могат да уловят типове само за движение; те могат да улавят стойности само чрез копиране или чрез препратка към lvalue. Въпреки че разбира се това е временен проблем, който се разрешава активно за C++14 ;)

„По-просто и ясно“ е въпрос на мнение. За прости случаи на обвързване, bind може да отнеме много по-малко въвеждане. bind също е фокусиран единствено върху обвързването на функции, така че ако видите std::bind, знаете какво гледате. Докато ако използвате ламбда, трябва да погледнете реализацията на ламбда, за да сте сигурни какво прави.

И накрая, C++ не отхвърля нещата само защото друга функция може да прави това, което прави. auto_ptr беше отхвърлен, тъй като е по своята същност опасен за използване и има алтернатива, която не е опасна.

person Nicol Bolas    schedule 24.03.2013
comment
+1. Изглежда има елемент в предстоящата книга на Effective на Скот Майерс 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
Въпреки че смятам, че с c++14 вероятно можете да замените std::bind напълно с lambdas (и аз най-вече го правя), все още ми харесва вашата точка за това, че 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
operator() на @Elliot Polly очевидно е const, така че не знам какво имате предвид. Кодът във въпроса се компилира добре, както и ламбда изразът в първия ми коментар по-горе. - person Jonathan Wakely; 02.09.2020
comment
Извинения. Глупаво пропуснах const. „Трябваше да погледна по-внимателно, преди да коментирам. - person Elliott; 03.09.2020