Можно ли?
От: ArtDenis Россия  
Дата: 08.06.03 10:47
Оценка:
Есть класс
class TGraphLine
{
  ...
public:
  ...
  bool CheckRectHit(const TPoint &cur);
  ...
};

// и вектор элементов этого класса
std::vector<TGraphLine> lines;


Чтобы найти элемент в векторе для которого CheckRectHit(..) по нужному аргументу возвращает true, я сделал такой шаблон:
template
<
  typename CLASS_NAME, // TGraphLine
  typename ARG_TYPE    // TPoint
>
class arg_pred_func
{
  const ARG_TYPE arg;
  bool (CLASS_NAME::*func)(const ARG_TYPE&);

public:
  arg_pred_func(bool (CLASS_NAME::*p)(const ARG_TYPE&), ARG_TYPE argument)
    : func(p),
      arg(argument)
  {
  }

  const bool operator()(CLASS_NAME &element) const
  {
    return (element.*func)(arg);
  }
};


Сам поиск происходит следующим образом:
  TPoint crd = Point(10, 20);

  std::vector<TGraphLine>::iterator it = std::find_if
  (
    lines.begin(),
    lines.end(),
    arg_pred_func<TGraphLine, TPoint>(&TGraphLine::CheckRectHit, crd)
  );
  ...


Так вот, появился вопрос, можно ли всё это сделать стандартными средствами (STL, boost), т.е. без собственного предиката. Что-то мне кажется, что я в очередной раз изобретаю велосипед.

Денис.
... << RSDN@Home 1.0 beta 7a >>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re: Можно ли?
От: МиГо  
Дата: 08.06.03 20:26
Оценка:
Может проще пройтись по элементам вектора, и для каждого
запустить его функцию?
Re: Можно ли?
От: NightWind Россия  
Дата: 08.06.03 21:25
Оценка:
Есть такие вещи как mem_fun и mem_fun_ref но им нельзя передавать параметры.....
Насчёт boost не знаю....

У вас функтор получился не адаптируемым, т.е. не поддерживает определения типов, его нужно наследовать от binary_function, т.е. такое не получится
  std::vector<TGraphLine>::iterator it = std::find_if
  (
    lines.begin(),
    lines.end(),
    not1(arg_pred_func<TGraphLine, TPoint>(&TGraphLine::CheckRectHit, crd))
  );
Posted via RSDN NNTP Server 1.6 beta

Исправлена подсветка синтаксиса. -- ПК.
Re: Можно ли?
От: dkon  
Дата: 09.06.03 07:50
Оценка: 5 (1)
Здравствуйте, ArtDenis, Вы писали:

если описать TGraphLine::CheckRectHit вот так:

bool CheckRectHit(TPoint cur) const;


можно использовать bind2nd:

std::vector<TGraphLine>::iterator it = std::find_if
(
    lines.begin(),
    lines.end(),
    bind2nd(mem_fun_ref(&TGraphLine::CheckRectHit), crd)
);
Re[2]: Можно ли?
От: ArtDenis Россия  
Дата: 09.06.03 16:36
Оценка:
Здравствуйте, МиГо, Вы писали:

МГ>Может проще пройтись по элементам вектора, и для каждого

МГ>запустить его функцию?

Конечно можно. Но тут дело немножко в другом. В случае с find_if код получается более читабельным. Когда я пишу find или find_if, то сразу видно, что я делаю именно поиск. Хотя это дело вкуса.

Денис.
... << RSDN@Home 1.0 beta 7a >>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[2]: Можно ли?
От: ArtDenis Россия  
Дата: 09.06.03 16:36
Оценка:
Здравствуйте, dkon, Вы писали:

D>если описать TGraphLine::CheckRectHit вот так:


D>
D>bool CheckRectHit(TPoint cur) const;
D>


К сожалению, такой подход снижает производительность из-за копирования объекта.

Денис.
... << RSDN@Home 1.0 beta 7a >>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re: Можно ли?
От: MaximE Великобритания  
Дата: 09.06.03 16:59
Оценка: 10 (1)
Здравствуйте, ArtDenis, Вы писали:

AD>Так вот, появился вопрос, можно ли всё это сделать стандартными средствами (STL, boost), т.е. без собственного предиката. Что-то мне кажется, что я в очередной раз изобретаю велосипед.


Элементарно с помощью boost::lambda.

Что-то типа (прошу не пинать — пишу без копилятора):

TPoint crd = Point(10, 20);
std::vector<TGraphLine>::iterator it(std::find_if
lines.begin(),
lines.end(),
boost::lambda::bind(&TGraphLine::CheckRectHit, crd, boost::lambda::_1));
Re[2]: Можно ли?
От: ArtDenis Россия  
Дата: 09.06.03 17:21
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Элементарно с помощью boost::lambda.

ME>Что-то типа (прошу не пинать — пишу без копилятора):
ME>
ME>TPoint crd = Point(10, 20);
ME>std::vector<TGraphLine>::iterator it(std::find_if
ME>lines.begin(),
ME>lines.end(),
ME>boost::lambda::bind(&TGraphLine::CheckRectHit, crd, boost::lambda::_1));
ME>


Спасибо, MaximE. то то что нужно! Единственная проблема в том, что у меня компилятор спотыкается на частичной специализации шаблонов из файла библиотеки boost::lambda
Поэтому сразу вопрос, а кому-нибудь удалось прикрутить boost::lambda на C++Builder4? И как дела обстоят с Builder'ами следующих версий?

Денис.
... << RSDN@Home 1.0 beta 7a >>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[3]: Можно ли?
От: dkon  
Дата: 09.06.03 17:25
Оценка:
Здравствуйте, ArtDenis, Вы писали:

AD>Здравствуйте, dkon, Вы писали:


D>>если описать TGraphLine::CheckRectHit вот так:


D>>
D>>bool CheckRectHit(TPoint cur) const;
D>>


AD>К сожалению, такой подход снижает производительность из-за копирования объекта.


TPoint не настолько большая структура, чтобы стоило об этом беспокоиться.
в общем случае, конечно, лучше передавать ссылку, но для этого придется поискать реализацию стл, которая не объявляет при этом ссылку на ссылку в bind2nd.
Re[3]: Можно ли?
От: WolfHound  
Дата: 09.06.03 17:56
Оценка: 8 (1)
Здравствуйте, ArtDenis, Вы писали:

AD>Спасибо, MaximE. то то что нужно! Единственная проблема в том, что у меня компилятор спотыкается на частичной специализации шаблонов из файла библиотеки boost::lambda

А если просто boost::bind без lambda?
class image;

class animation
{
public:

    void advance(int ms);
    bool inactive() const;
    void render(image & target) const;
};

std::vector<animation> anims;

template<class C, class P> void erase_if(C & c, P pred)
{
    c.erase(std::remove_if(c.begin(), c.end(), pred), c.end());
}

void update(int ms)
{
    std::for_each(anims.begin(), anims.end(), boost::bind(&animation::advance, _1, ms));
    erase_if(anims, boost::mem_fn(&animation::inactive));
}

void render(image & target)
{
    std::for_each(anims.begin(), anims.end(), boost::bind(&animation::render, _1, boost::ref(target)));
}

erase_if ИМХО лучше брать тут.
Автор: WolfHound
Дата: 30.05.03
... << RSDN@Home 1.0 beta 6a >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Можно ли?
От: Юнусов Булат Россия  
Дата: 09.06.03 18:10
Оценка: 10 (1)
Здравствуйте, ArtDenis, Вы писали:

Используйем ПОИСК
ищем find_if
первая же ссылка которую получаем
http://rsdn.ru/Forum/Message.aspx?mid=180538
Автор: Юнусов Булат
Дата: 23.01.03


Обтачиваем напильником под твою задачу (под константную ссылку)

    std::vector<TGraphLine>::iterator it = std::find_if(lines.begin(), lines.end(), 
        boost::bind( &TGraphLine::Hit, _1, boost::cref(pt) )
        );
Re[4]: Можно ли?
От: MaximE Великобритания  
Дата: 09.06.03 18:32
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>А если просто boost::bind без lambda?


Можно и просто. Но для того чтобы, например, инвертировать результат функтора boost::bind его придется заворачивать в std::not<>, а lambda просто написать !boost::lambda::bind(...).
Re[4]: Можно ли?
От: ArtDenis Россия  
Дата: 09.06.03 19:31
Оценка:
Здравствуйте, WolfHound, Вы писали:
AD>>Спасибо, MaximE. то то что нужно! Единственная проблема в том, что у меня компилятор спотыкается на частичной специализации шаблонов из файла библиотеки boost::lambda
WH>А если просто boost::bind без lambda?
WH>...
ОК, работает.
... << RSDN@Home 1.0 beta 7a >>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[2]: Можно ли?
От: ArtDenis Россия  
Дата: 09.06.03 19:31
Оценка:
Здравствуйте, Юнусов Булат, Вы писали:

ЮБ>Используйем ПОИСК

ЮБ>Обтачиваем напильником под твою задачу (под константную ссылку)
ЮБ>...

Спасибо.
... << RSDN@Home 1.0 beta 7a >>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[2]: Можно ли?
От: MaximE Великобритания  
Дата: 10.06.03 07:04
Оценка:
Здравствуйте, dkon, Вы писали:

D>Здравствуйте, ArtDenis, Вы писали:


D>если описать TGraphLine::CheckRectHit вот так:


D>
D>bool CheckRectHit(TPoint cur) const;
D>


D>можно использовать bind2nd:


D>
D>std::vector<TGraphLine>::iterator it = std::find_if
D>(
D>    lines.begin(),
D>    lines.end(),
D>    bind2nd(mem_fun_ref(&TGraphLine::CheckRectHit), crd)
D>);
D>


По-моемому, здесь нужен bind1st, а не 2nd.
Re[4]: Можно ли?
От: ArtDenis Россия  
Дата: 10.06.03 07:39
Оценка:
По-моему, Jaakko Jarvi нужно поставить памятник за boost::bind

Кстати, подстановки типа _1, _2 ... впервые появились в boost, или кто-то раньше догадался использовать такие вещи?

Денис.
... << RSDN@Home 1.0 beta 7a >>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[3]: Можно ли?
От: dkon  
Дата: 10.06.03 12:51
Оценка:
Здравствуйте, MaximE, Вы писали:

D>>
D>>std::vector<TGraphLine>::iterator it = std::find_if
D>>(
D>>    lines.begin(),
D>>    lines.end(),
D>>    bind2nd(mem_fun_ref(&TGraphLine::CheckRectHit), crd)
D>>);
D>>


ME>По-моемому, здесь нужен bind1st, а не 2nd.


нет, первый параметр mem_fun1_ref_t::operator() -- адрес функции-мембера.
Re[4]: Можно ли?
От: dkon  
Дата: 10.06.03 12:55
Оценка:
Здравствуйте, dkon, Вы писали:

D>Здравствуйте, MaximE, Вы писали:



D>нет, первый параметр mem_fun1_ref_t::operator() -- адрес функции-мембера.


тьфу, ссылка на класс, конечно, а не адрес функции.
Re[5]: Можно ли?
От: Павел Кузнецов  
Дата: 11.06.03 17:47
Оценка:
Здравствуйте, ArtDenis, Вы писали:

A> Кстати, подстановки типа _1, _2 ... впервые появились в boost, или

A> кто-то раньше догадался использовать такие вещи?

Можно посмотреть документацию в boost. До того, как boost.lambda вошла в boost,
она называлась как-то по-другому и жила самостоятельной жизнью. Кроме того,
если я не ошибаюсь, существовало несколько альтернативных библиотек
с аналогичной функциональностью.
Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.