Russian Qt Forum

Программирование => С/C++ => Тема начата: sergeyvl12 от Октябрь 19, 2009, 12:20



Название: Использование find_if [РЕШЕНО]
Отправлено: sergeyvl12 от Октябрь 19, 2009, 12:20
Добрый день,

class SomeClass
{
    ...
public:
    int getSomeValue() const;
    ...
};

...

std::vector<SomeClass> values;

так вот, хочу с помощью std::find_if найти первое значение больше 0.

Свой функционал писать не хочу. Можно ли выкрутиться стандартными?



Название: Re: Использование find_if
Отправлено: crackedmind от Октябрь 19, 2009, 15:54
Напиши свой предикат, который будешь передавать в find_if


Название: Re: Использование find_if
Отправлено: sergeyvl12 от Октябрь 19, 2009, 16:00
Напиши свой предикат, который будешь передавать в find_if

Может быть я не точно выразился, но я сказал что свой функционал (или предикат, если так больше нравится) писать не хочу.

С предикатом было бы просто:

std::find_if(values.begin(),values.end(),MyPredicate())

однако вопрос в том, можно ли составить этот предикат, используя стандартные и не реализуя класс MyPredicate ?


Название: Re: Использование find_if
Отправлено: crackedmind от Октябрь 19, 2009, 16:14
Для своих типов данных придется писать.


Название: Re: Использование find_if
Отправлено: Tonal от Октябрь 20, 2009, 07:31
Код:
std::find_if(values.begin(), values.end(), bind(&SomeClass::getSomeValue, _1) > 0);
Оно?
bind ищи в Boost-е или в stl нового стандарта. :)
В  gcc 4.4.0 это пространство имён stl::tr1


Название: Re: Использование find_if
Отправлено: sergeyvl12 от Октябрь 20, 2009, 14:42
Код:
std::find_if(values.begin(), values.end(), bind(&SomeClass::getSomeValue, _1) > 0);
Оно?
bind ищи в Boost-е или в stl нового стандарта. :)
В  gcc 4.4.0 это пространство имён stl::tr1

Спасибо, это видимо оно. Только нет у меня сейчас нового стандарта :( (Visual Age С++ 6.0 под AIX)


Название: Re: Использование find_if
Отправлено: Tonal от Октябрь 21, 2009, 08:29
Ну и посмотри в его доке чего именно он поддерживает.
Посмотри в доке на свою версию Boost-а про AIX.


Название: Re: Использование find_if
Отправлено: sergeyvl12 от Октябрь 22, 2009, 11:20
Ну и посмотри в его доке чего именно он поддерживает.
Посмотри в доке на свою версию Boost-а про AIX.

boost скомпилить под аиксом не удается целяком (старый компилятор). Реализация stl под AIX такие вещи делать не умеет.

Нашли относительно безболезненный выход: перетянули compose1 (есть не во всех версиях stl).

Теперь это выглядит так;

Код:
std::vector<SomeClass>::iterator iter =
        std::find_if(values.begin(),
                     values.end(),
                     aux::compose1(std::bind2nd(std::greater<int>(),0),
                                   std::mem_fun_ref(&SomeClass::getSomeValue)));



Название: Re: Использование find_if
Отправлено: crackedmind от Октябрь 23, 2009, 05:03
А не проще было предикат свой написать? :)


Название: Re: Использование find_if
Отправлено: Tonal от Октябрь 23, 2009, 08:49
Boost "целиком" компилить не нужно. Там большинство библиотек - только в хедерах. И bind, и lambda именно такие.
Так что вам нужно было просто проверить компиляемость. :)


Название: Re: Использование find_if
Отправлено: sergeyvl12 от Октябрь 23, 2009, 10:45
А не проще было предикат свой написать? :)

Да оно то может быть и проще если предикат достаточно сложный. Но дело в том что это в таких простых случаях усложняет читабельность и сопровождаемость кода ( для дого чтобы понять что происходит в коде, приходится смотреть предикат, который может быть описан не здесь, а где-то ). А так все перед глазами. Конечно форма с compose1 - это тоже не выход (слишком громоздко и не читабельно). Поэтому буду пробивать boost.


Название: Re: Использование find_if
Отправлено: sergeyvl12 от Октябрь 23, 2009, 11:02
Boost "целиком" компилить не нужно. Там большинство библиотек - только в хедерах. И bind, и lambda именно такие.
Так что вам нужно было просто проверить компиляемость. :)


Это да, но с другой стороны:

1. Даже если это и хидера - их так просто не вытащишь (потому что они как правило зависят от других частей буста);
2. Желательно также было бы к boost::bind иметь какие-то тесты чтобы проверить что оно хотя-бы работает под аиксом.

В связи с этим вопрос - как корректно установить буст частично (на данный момент мне нужен boost::bind + тксты к нему). Возможно ли это? В инсталляторе буста я пока не разобрался.


Название: Re: Использование find_if
Отправлено: crackedmind от Октябрь 23, 2009, 12:51
В составе буста идет прога которая вытаскивает нужную либу с минимальными зависимостями.

Цитировать
The bcp utility is a tool for extracting subsets of Boost, it's useful for Boost authors who want to distribute their library separately from Boost, and for Boost users who want to distribute a subset of Boost with their application.

bcp can also report on which parts of Boost your code is dependent on, and what licences are used by those dependencies.


Название: Re: Использование find_if
Отправлено: Tonal от Октябрь 27, 2009, 09:43
В связи с этим вопрос - как корректно установить буст частично (на данный момент мне нужен boost::bind + тксты к нему). Возможно ли это? В инсталляторе буста я пока не разобрался.
Эжели используются только header-only либы - то всё просто.
 1. Утянул последний архивчик с сайта,
 2. Развернул его куда-нибудь.
 3. Добавил путь к этому куда-нибудь в пути инклюдов проекта. :)


Название: Re: Использование find_if
Отправлено: sergeyvl12 от Октябрь 28, 2009, 10:48
Спасибо всем кто ответил.

Резюмирую:

1. Вычленять что-то из буста наверное нет смысла. Попробовал с помощью bcp вычленить bind. Оказалось что вычленилось где-то 500 файлов (из 7000);
2. Лучше поставить весь буст и юзать пока только хидера (вернее те из них что сможет подхватить наш древний компилятор )
3. Поставил буст, написал тест для bind:

Код:
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>

#include <boost/bind/bind.hpp>

class Person
{
    std::string name_;

public:
    Person( const std::string& name )
        : name_( name )
    {}

    std::string getName() const
    { return name_; }
};

int main()
{
    std::vector<Person> people;

    people.push_back(Person("Jack"));
    people.push_back(Person("John"));
    people.push_back(Person("Martin"));
    people.push_back(Person("Peter"));

    std::vector<Person>::iterator
        iter(std::find_if(people.begin(), people.end(), boost::bind( &Person::getName, _1 ) == "Peter" ));

    std::cout << iter->getName() << std::endl;
}

тест заработал.

Значит как минимум bind можно использовать.

Постепенно начнем использовать и другие библиотеки. Всем спасибо.