Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > boost::bind - для двух предикатов


Автор: boostcoder 18.12.2010, 19:29
Всем привет.
Вот любопытно, кто и как, переписал бы этот код с использованием boost::bind() вместо pred().
Код

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

bool _pred1(int v) {
   return v > 5;
}
bool _pred2(int v) {
   return v < 11;
}
bool pred(int v) {
   return _pred1(v) && _pred2(v);
}

int main() {
   std::vector<int> iv({3,4,5,67,7,6,45,3,23,4,5,67,8,8,6,4,3}), iv2;

   std::copy_if(iv.begin(), iv.end(), std::back_inserter(iv2), pred);
   std::copy(iv2.begin(), iv2.end(), std::ostream_iterator<int>(std::cout, ", "));
}

http://liveworkspace.org/code/76204a07cf591e656f3302ba715bf863
т.е. интересует именно способ избавления от pred(). _pred1() и _pred2() допустим библиотечные функции.

Автор: boostcoder 18.12.2010, 19:48
напрашивается что-то типа:
Код

boost::bind(
   boost::bind(_pred1, _1),
   boost::bind(_pred2, _1)
);

но это не правильно..

Автор: mes 18.12.2010, 20:37
Цитата(boostcoder @  18.12.2010,  18:48 Найти цитируемый пост)
но это не правильно.. 

logical_and забыто..

Добавлено через 1 минуту и 53 секунды
Код

   std::copy_if(iv.begin(), iv.end(), std::back_inserter(iv2)   
     , std::bind(std::logical_and<bool>()
       , std::bind(_pred1, std::placeholders::_1)
        , std::bind(_pred2, std::placeholders::_1 ) ) );


http://liveworkspace.org/code/d50c1e6bda8e9e051b306d3cb645eda0

Автор: boostcoder 18.12.2010, 20:41
Цитата(mes @  18.12.2010,  20:37 Найти цитируемый пост)
logical_and забыто..

ага. а я полез в boost.lambda искать способ smile 

спасибо огромное smile

Добавлено через 8 минут и 41 секунду
но вопрос еще не закрыт. интересует следующее.
можно ли как-то создать шаблон, который сможет в качестве параметров принимать функторы, и дополнительным параметром принимать logical_*. есть идеи?
что-то типа:
Код

std::copy_if(iv.begin(), iv.end(), std::back_inserter(iv2)   
   predicate<
      std::bind(_pred1, std::placeholders::_1),
      std::bind(_pred2, std::placeholders::_1),
      std::logical_and<bool>
   ::type()
);

Автор: mes 18.12.2010, 20:50
Цитата(boostcoder @  18.12.2010,  19:41 Найти цитируемый пост)
ага. а я полез в boost.lambda искать способ 

лямбда тоже поможет

Цитата(boostcoder @  18.12.2010,  19:41 Найти цитируемый пост)
спасибо огромное  

пож smile

Автор: boostcoder 18.12.2010, 20:55
Цитата(boostcoder @  18.12.2010,  20:41 Найти цитируемый пост)
можно ли как-то создать шаблон, который сможет в качестве параметров принимать функторы, и дополнительным параметром принимать logical_*. есть идеи?

ага. понял. сейчас..

Автор: Earnest 20.12.2010, 15:10
boostcoder, я так понимаю, ты сейчас бустом увлечен по самые уши. Но имей в виду следующее. Когда в коде видишь трехэтажный байнд, хочется найти автора и кое-что ему оторвать ... (руки, если что).
In real life полезны только простые байнды, которые читаются на раз, без лишнего напряжения извилин, которые обычно заняты чем-нибудь еще. Поддерживать зашифрованный переизбытком буста код очень тяжело.
Я тоже сначала этим делом увлекалась, каждый цикл с итераторами норовила алгоритмом заменить, ну и в таком духе. Прошло, после возвратов к коду годичной давности. Забайндить можно многое, но далеко не все следует делать. 
Так что знай меру и будь проще. Это, конечно, не только к бусту относится.

Автор: boostcoder 20.12.2010, 20:05
Цитата(Earnest @  20.12.2010,  15:10 Найти цитируемый пост)
Но имей в виду следующее. Когда в коде видишь трехэтажный байнд, хочется найти автора и кое-что ему оторвать

согласен, если в коде увидеть такое:
Код

   std::copy_if(iv.begin(), iv.end(), std::back_inserter(iv2)   
     , std::bind(std::logical_and<bool>()
       , std::bind(_pred1, std::placeholders::_1)
        , std::bind(_pred2, std::placeholders::_1 ) ) );

но а если так?:
Код

   std::copy_if(iv.begin(), iv.end(), std::back_inserter(iv2),
      and_pred<...>()
);

разве не очевидней и понятней? smile 

Цитата(Earnest @  20.12.2010,  15:10 Найти цитируемый пост)
Я тоже сначала этим делом увлекалась, каждый цикл с итераторами норовила алгоритмом заменить

так и делаю. не люблю циклы в коде. что в этом плохого?
понятней ведь использование copy_if() и подобных, чем, к примеру, цикл с if`ами smile 
ну а for или while без if`ов, т.е. просто для копирования, вообще нелепо смотрится. разве нет?

Добавлено через 4 минуты и 16 секунд
Цитата(Earnest @  20.12.2010,  15:10 Найти цитируемый пост)
будь проще. Это, конечно, не только к бусту относится.

не понял.. это намек на что-то личное? smile 

Автор: borisbn 20.12.2010, 20:52
boostcoder, в чём-то согласен с Earnest ( кроме
Цитата(Earnest @  20.12.2010,  15:10 Найти цитируемый пост)
Так что знай меру и будь проще. Это, конечно, не только к бусту относится.

. это, наверное, действительно что-то личное smile )
тебе часто приходилось поддерживать/изменять чужой код ?
если в нём всё натыкано предикатами, функторами и т.п., и если там всё работает так как надо, то выглядит это оч.хор., но если нужно что-то изменить - обычный цикл ( for или while ) - гораздо проще. в сопровождении, конечно, а не просто в чтении/понимании кода

Автор: boostcoder 20.12.2010, 21:00
Цитата(borisbn @  20.12.2010,  20:52 Найти цитируемый пост)
но если нужно что-то изменить - обычный цикл ( for или while ) - гораздо проще.

наоборот smile

Добавлено через 1 минуту и 23 секунды
Цитата(borisbn @  20.12.2010,  20:52 Найти цитируемый пост)
это, наверное, действительно что-то личное

я с Earnest не знаком. вроде даже нигде не пересекались smile 

Автор: borisbn 20.12.2010, 21:05
функтор ещё нужно найти в чужом коде (хотя... с томатоАссистентом - но проблем), и к тому же, возможно, при изменении этого функтора заденутся другие места программы, а тебе нужно поменять только в этом месте... Ладно. IMHO этот холивор такой же бессмысленный и беспощадный, как far vs Total или Ctrl+C vs Ctrl+Ins :

Автор: mes 20.12.2010, 21:12
Цитата(boostcoder @  20.12.2010,  19:05 Найти цитируемый пост)
но а если так?:

тогда уж если делать, то, имхо, чтоб было хотя бы так :
 std::copy_if(iv.begin(), iv.end(), std::back_inserter(iv2)  ,  my_bind  ( logical_and, _pred1, _pred2 ) );

считаем что лямбды нам запретили..

Автор: boostcoder 20.12.2010, 21:15
Цитата(borisbn @  20.12.2010,  21:05 Найти цитируемый пост)
IMHO этот холивор такой же бессмысленный и беспощадный, как far vs Total или Ctrl+C vs Ctrl+Ins

нет. я в этом вижу гибкость проектирования.
при использовании цикла, тебе нужно чтоб он имел в распоряжении все переменные/объекты которыми оперирует. это монолит. нужно следить за точками входа/выхода.
а при использовании предикатов, ты отвязываешься от локального кода в котором предикат используется. всю необходимую информацию о точках входа/выхода нет надобности держать в голове. получается своего рода изолированность от локального блока кода. всю информацию которая необходима предикату, ты передаешь ему в конструктор. smile

Добавлено @ 21:18
Цитата(mes @  20.12.2010,  21:12 Найти цитируемый пост)
my_bind  ( logical_and, _pred1, _pred2 )

слишком много деталей..
если у предиката имя типа "and_pred", и видно что он используется в std::copy_if(), то(по крайней мере мне) становится понятно его внутренее устройство.

Добавлено через 5 минут и 43 секунды
Цитата(mes @  20.12.2010,  21:12 Найти цитируемый пост)
считаем что лямбды нам запретили..

пока - да

Автор: mes 20.12.2010, 21:34
Цитата(boostcoder @  20.12.2010,  20:15 Найти цитируемый пост)
слишком много деталей..

согласен.. 

Цитата(boostcoder @  20.12.2010,  20:15 Найти цитируемый пост)
если у предиката имя типа "and_pred"

частично согласен.. 

Цитата(boostcoder @  20.12.2010,  19:05 Найти цитируемый пост)
and_pred<...>()

не согласен с конструкцией..
 smile 

Автор: boostcoder 20.12.2010, 21:43
Цитата(mes @  20.12.2010,  21:34 Найти цитируемый пост)
не согласен с конструкцией..

предлагаете шаблонный конструктор?

Автор: mes 20.12.2010, 21:43
действительно, хорошо бы иметь шаблон предиката для стл, алгоритмов, разгружающий бинд..
только он должен быть простым предикатом, а не and_pred.. 

a боост::лямбду тоже запретили ?

Автор: boostcoder 20.12.2010, 21:48
Цитата(mes @  20.12.2010,  21:43 Найти цитируемый пост)
a боост::лямбду тоже запретили ?

в этой теме, мне действительно интересно реализация этого без лямбды.


Добавлено через 1 минуту и 26 секунд
Цитата(mes @  20.12.2010,  21:43 Найти цитируемый пост)
он должен быть простым предикатом, а не and_pred

что именно в "and_pred" не нравится?

Автор: mes 20.12.2010, 21:53
Цитата(boostcoder @  20.12.2010,  20:48 Найти цитируемый пост)
что именно в "and_pred" не нравится? 

префикс "and" который заставляет изготавливать несколько однообразных предикатов.. 

сейчас попробую наваять как я себе представляю.. 

Автор: boostcoder 20.12.2010, 21:55
Цитата(mes @  20.12.2010,  21:53 Найти цитируемый пост)
префикс "and"

ааа.. так он появился из-за моей задачи smile 
а в идеале, да, должен еще и логический предикат указываться. хотя..группа предикатов and_*, or_* тоже бы облегчила понимание.

Автор: mes 20.12.2010, 22:11
вот грубый набросок: http://liveworkspace.org/code/d649be290aaa29b4ab02824b4353dffa
чтоб выглядило прилично, нужно поднапрячься.. но неохота.. главное смысл понятен,
как получать композиционный отложенный предикат.. 
 smile  

Автор: Earnest 21.12.2010, 11:09
Цитата(boostcoder @  20.12.2010,  21:05 Найти цитируемый пост)
не понял.. это намек на что-то личное? 

Почему сразу личное? Это я про программирование вообще. Не только бустом можно код зашифровать.
И я вовсе не против алгоритмов и предикатов. Если код с алгоритмом-предикатом-байндом выглядит ясно, то здорово. Просто не надо это самоцелью делать.

Автор: boostcoder 21.12.2010, 11:11
Цитата(Earnest @  21.12.2010,  11:09 Найти цитируемый пост)
Не только бустом можно код зашифровать.

 smile 

Цитата(Earnest @  21.12.2010,  11:09 Найти цитируемый пост)
Просто не надо это самоцелью делать.

так нет же. цель - улучшить стиль. подглядывание стиля из буста, очень помогает.

Автор: Earnest 21.12.2010, 11:14
 А навеяно вот чем:
слишком много усилий тратится на то, чтобы придумать супер-шаблон, в который можно запихать 2 или больше предиката, да чтобы все это еще хорошо выглядело... Как академическая, задачка интересная, да. Но на практике... какой алгоритм (я имею в виду обработку каких-нибудь данных, практичную) за это время можно было бы написать... 
Короче, время на заточку лопаты нужно разумно регулировать. Туда ведь не только время, но и мозговая энергия уходит...
Работодатель тебе за что платит-то? Ведь не за байндеры хитрые?

Автор: boostcoder 21.12.2010, 11:21
Цитата(Earnest @  21.12.2010,  11:14 Найти цитируемый пост)
Но на практике... какой алгоритм (я имею в виду обработку каких-нибудь данных, практичную) за это время можно было бы написать...

шаблон пишется один раз. вставляется в какой-нибудь utils.hpp, и используется во всем проекте.
нет, конечно, если в задаче использование этого шаблона происходит все раз - то разрабатывать его нет смысла.
но после того, как он уже разработан, скопипастить его много времени не занимает.

Автор: null56 10.1.2011, 01:37
немного с опозданием, но пускай останется для истории
бустовский bind поддерживает логические операции, что позволяет избавиться от одного уровня с logical_and
Цитата

Overloaded operators (new in Boost 1.33)
For convenience, the function objects produced by bind overload the logical not operator ! and the relational and logical operators ==, !=, <, <=, >, >=, &&, ||.

вместо
Код

 std::copy_if(iv.begin(), iv.end(), std::back_inserter(iv2), bind(std::logical_and<bool>(), std::bind(_pred1, std::placeholders::_1) , std::bind(_pred2, std::placeholders::_1 ) ) );

можно короче
Код

std::copy_if(iv.begin(), iv.end(), std::back_inserter(iv2), boost :: bind(_pred1, _1) && boost :: bind(_pred2, _1));

Автор: boostcoder 10.1.2011, 01:42
Цитата(null56 @  10.1.2011,  01:37 Найти цитируемый пост)
бустовский bind поддерживает логические операции

это я знал, т.к. регулярно использую operator!() с баиндами. но мне и в голову не пришло что можно таким образом комбинировать функциональные объекты...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)