у меня есть foo
который является std::vector<int>
, Он представляет «крайние» значения для набора диапазонов.
Например, если foo
равен {1, 3, 5, 7, 11}, то диапазоны составляют 1-3, 3-5, 5-7, 7-11. Для меня это значимо 4 периода. Обратите внимание, что каждый период включает в себя первое число в диапазоне, а не последнее. Так что в моем примере 8 появляется в 3-м (нулевом) периоде. 7 также появляется в 3-м периоде. 11 и выше нигде не появляется. 2 появляется в 0-м периоде.
Учитывая bar
который является int
, Я использую
std::find_if(
foo.begin(),
foo.end(),
std::bind2nd(std::greater<int>(), bar)
) - foo().begin() - 1;
чтобы дать мне период, который должен содержать bar
,
Моя проблема: std::bind2nd
не рекомендуется, поэтому я должен рефакторинг. Что такое эквивалентное утверждение, использующее обновленные функции? std::bind
не «заглядывает» очевидным образом.
В C ++ 11 вы можете использовать std::bind
; просто не так очевидно, как его использовать:
#include <functional>
using namespace std::placeholders;
std::find_if(
foo.begin(),
foo.end(),
// create a unary function object that invokes greater<int>::operator()
// with the single parameter passed as the first argument and `bar`
// passed as the second argument
std::bind(std::greater<int>(), _1, bar)
) - foo().begin() - 1;
Ключом является использование аргумента заполнителя, который объявлен в std::placeholders
Пространство имен. std::bind
возвращает объект функции, который принимает некоторое количество параметров при вызове. Заполнители, используемые внутри вызова std::bind
покажите, как аргументы, предоставляемые при вызове результирующего объекта, отображаются в списке аргументов для вызываемого объекта, к которому вы привязываетесь. Так, например:
auto op1 = std::bind(std::greater<int>(), _1, bar);
op1(5); // equivalent to std::greater<int>()(5, bar)
auto op2 = std::bind(std::greater<int>(), bar, _1);
op2(5); // equivalent to std::greater<int>()(bar, 5)
auto op3 = std::bind(std::greater<int>(), _2, _1);
op3(5, bar); // equivalent to std::greater<int>()(bar, 5)
auto op4 = std::bind(std::greater<int>(), _1, _2);
op4(5, bar); // equivalent to std::greater<int>()(5, bar)
Как насчет идти прямо из каменного века (bind2nd
) к железному веку с общей лямбдой C ++ 14, минуя бронзовый век (bind
)?
std::find_if(foo.begin(), foo.end(), [&](auto const& elem) {
return elem > bar;
});
И если вход отсортирован
std::lower_bound(foo.begin(), foo.end(), bar);
Лямбды читаются намного проще, и их легче встроить, чем std::bind
. как выражения Смотрите, например CaveCon 2015 Лавевея говорить.
bind
версия будет:
bind(std::greater<int>(), placeholders::_1, bar)
но я думаю, что больше рекомендуется использовать лямбды, как в:
[bar](const int a){return bar < a;}
Также рекомендуется использовать перегруженные функции begin/end
вместо вызовов методов. так было бы как:
find_if(begin(foo), end(foo), [bar](const int a){return bar < a;})