Варим кашу в буст - lambda + bind + shared_ptr
От: AgIle Россия  
Дата: 29.08.06 10:42
Оценка:
Всем привет!


class IDownloaderObserver
{
public:
    virtual void OnCompleted(CString const& fileName)    =0;
};

typedef shared_ptr<IDownloaderObserver> IDownloaderObserverPtr;

typedef vector<IDownloaderObserverPtr> DownloadObservers;

class DownloadSubject
{
public:
    void registerObserver(IDownloaderObserverPtr observer);
    void removeObserver(IDownloaderObserverPtr observer);

protected:
    void notifyCompleted(CString const& fileName);

private:
    /*DownloadObservers*/ vector<IDownloaderObserver*> downloadObservers;
};

void DownloadSubject::notifyCompleted(CString const& fileName)
{
    for_each(    downloadObservers.begin(),
            downloadObservers.end(),
            lambda::bind(&IDownloaderObserver::OnCompleted, lambda::_1, fileName)    );

}


Выше приведенный код прекрастно компилируется...
Но давайте изменим тип downloadObservers на DownloadObservers ...
Как теперь заставить его работать? Пишет ошибку:

c:\Agile\libr\boost\include\boost-1_33_1\boost\lambda\detail\actions.hpp(96): error C2665: 'boost::lambda::function_adaptor<Func>::apply' : none of the 2 overloads can convert parameter 2 from type 'std::allocator<_Ty>::value_type'
with
[
Func=boost::lambda::return_type_N<boost::lambda::function_action<3>,boost::lambda::lambda_functor_base<boost::lambda::action<3,boost::lambda::function_action<3>>,boost::tuples::tuple<const boost::lambda::detail::bind_traits<void (__thiscall IDownloaderObserver::* const )(const CString &)>::type,const boost::lambda::detail::bind_traits<const boost::lambda::placeholder1_type>::type,const boost::lambda::detail::bind_traits<const CString>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type>>::sig<boost::tuples::tuple<std::allocator<IDownloaderObserverPtr>::value_type &,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>>::rets_t>::plain_Func
]
and
[
_Ty=IDownloaderObserverPtr
]

Re: Варим кашу в буст - lambda + bind + shared_ptr
От: zaufi Земля  
Дата: 29.08.06 11:37
Оценка: 2 (1)
Здравствуйте, AgIle, Вы писали:

AI>Всем привет!


AI>

AI>class IDownloaderObserver
AI>{
AI>public:
AI>    virtual void OnCompleted(CString const& fileName)    =0;
AI>};

AI>typedef shared_ptr<IDownloaderObserver> IDownloaderObserverPtr;

AI>typedef vector<IDownloaderObserverPtr> DownloadObservers;

AI>class DownloadSubject
AI>{
AI>public:
AI>    void registerObserver(IDownloaderObserverPtr observer);
AI>    void removeObserver(IDownloaderObserverPtr observer);

AI>protected:
AI>    void notifyCompleted(CString const& fileName);

AI>private:
AI>    /*DownloadObservers*/ vector<IDownloaderObserver*> downloadObservers;
AI>};

AI>void DownloadSubject::notifyCompleted(CString const& fileName)
AI>{
AI>    for_each(    downloadObservers.begin(),
AI>            downloadObservers.end(),
AI>            lambda::bind(&IDownloaderObserver::OnCompleted, lambda::_1, fileName)    );

AI>}

AI>


AI>Выше приведенный код прекрастно компилируется...

AI>Но давайте изменим тип downloadObservers на DownloadObservers ...

во-первых для таких простых вещей lambda не нужна... достаточно просто boost::bind (не путать с boost::lambda::bind)
во-вторых DownloadObservers это не тоже самое что vector<IDownloaderObserver*>? чуйствуешь разницу?

хинт: в первом случае в векторе лежат _не_указатели_ а _объекты_ shared_ptr из которых еще надо достать указатель и только после этого вызывать евоный OnComplete! т.е. буит както так:
using namespace boost;
for_each(
    downloadObservers.begin()
  , downloadObservers.end()
  , bind(
        &IDownloaderObserver::OnCompleted
      , bind(&DownloadObservers::value_type::get, _1)
      , fileName
      )
  );
Re[2]: Варим кашу в буст - lambda + bind + shared_ptr
От: zaufi Земля  
Дата: 29.08.06 11:48
Оценка:
а вообще все это смахивает на велосипед
посмари в сторону boost::signals и не городи огород
Re[2]: Варим кашу в буст - lambda + bind + shared_ptr
От: shank  
Дата: 29.08.06 11:58
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>хинт: в первом случае в векторе лежат _не_указатели_ а _объекты_ shared_ptr из которых еще надо достать указатель и только после этого вызывать евоный OnComplete!

А разве bind сам этого не умеет делать?
Re[3]: Варим кашу в буст - lambda + bind + shared_ptr
От: zaufi Земля  
Дата: 29.08.06 12:07
Оценка:
Здравствуйте, shank, Вы писали:

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


Z>>хинт: в первом случае в векторе лежат _не_указатели_ а _объекты_ shared_ptr из которых еще надо достать указатель и только после этого вызывать евоный OnComplete!

S>А разве bind сам этого не умеет делать?

а как ты се это преставляешь??

г-н AgIle пытаица заbindить метод IDownloaderObserver'a а for_each упорно пихает в функтор объекты shared_ptr<IDownloaderObserver> -- дело тут совершенно не в bind'e -- товарисча грязно обругивает несогласный (обоснованно) компилятор (который не может вызвать IDownloaderObserver::OnCompleted у shared_ptr'a и пребывает в растерянности от беспардонных действий юзера )
Re[4]: Варим кашу в буст - lambda + bind + shared_ptr
От: shank  
Дата: 29.08.06 12:10
Оценка:
Здравствуйте, zaufi, Вы писали:

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


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


Z>>>хинт: в первом случае в векторе лежат _не_указатели_ а _объекты_ shared_ptr из которых еще надо достать указатель и только после этого вызывать евоный OnComplete!

S>>А разве bind сам этого не умеет делать?

Z>а как ты се это преставляешь??

Я многое в бусте плохо себе представляю.
Z>г-н AgIle пытаица заbindить метод IDownloaderObserver'a а for_each упорно пихает в функтор объекты shared_ptr<IDownloaderObserver> -- дело тут совершенно не в bind'e -- товарисча грязно обругивает несогласный (обоснованно) компилятор (который не может вызвать IDownloaderObserver::OnCompleted у shared_ptr'a и пребывает в растерянности от беспардонных действий юзера )
Но так ведь работает
#include <iostream>
#include <algorithm>
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>

class A
{
public:
    virtual void memfn() = 0;
};

class B : public A
{
    int i_;
public:
    B(int i = 0):i_(i){}
    void memfn() { std::cout << "B::memfn() " << i_ << '\n'; }
};

typedef boost::shared_ptr<A> sptr;

int main()
{
    std::vector<sptr> v;
    v.push_back(sptr(new B(1)));
    v.push_back(sptr(new B(3)));
    v.push_back(sptr(new B(5)));
    v.push_back(sptr(new B(7)));
    v.push_back(sptr(new B(9)));
    
    std::for_each(v.begin(), v.end(), bind(&A::memfn, _1));
}
Re[5]: Варим кашу в буст - lambda + bind + shared_ptr
От: zaufi Земля  
Дата: 29.08.06 12:26
Оценка:
Здравствуйте, shank, Вы писали:

S>Но так ведь работает


девствителна!
благодаря одной спец функции -- get_pointer() перегруженой для shared_ptr

но это не работает для boost::lambda::bind...
Re[2]: Варим кашу в буст - lambda + bind + shared_ptr
От: AgIle Россия  
Дата: 29.08.06 13:38
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>
Z>using namespace boost;
Z>for_each(
Z>    downloadObservers.begin()
Z>  , downloadObservers.end()
Z>  , bind(
Z>        &IDownloaderObserver::OnCompleted
Z>      , bind(&DownloadObservers::value_type::get, _1)
Z>      , fileName
Z>      )
Z>  );

Z>


Спасибо, можно проще:

for_each(
          downloadObservers.begin()
        , downloadObservers.end()
        , boost::bind(
                      &IDownloaderObserver::OnCompleted
                    , _1
                    , fileName)
        );


http://www.boost.org/libs/bind/bind.html#with_member_pointers
Re[3]: Варим кашу в буст - lambda + bind + shared_ptr
От: zaufi Земля  
Дата: 29.08.06 13:43
Оценка:
Здравствуйте, AgIle, Вы писали:

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


AI>Спасибо, можно проще:


мы уже здесь
Автор: zaufi
Дата: 29.08.06
обсудили благодаря чему это работет
Re[3]: Варим кашу в буст - lambda + bind + shared_ptr
От: shank  
Дата: 29.08.06 16:58
Оценка:
Здравствуйте, AgIle, Вы писали:

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

AI>Спасибо, можно проще:

AI>
AI>for_each(
AI>          downloadObservers.begin()
AI>        , downloadObservers.end()
AI>        , boost::bind(
AI>                      &IDownloaderObserver::OnCompleted
AI>                    , _1
AI>                    , fileName)
AI>        );
AI>

Можно еще чуть проще — не писать префикс boost::, если используются placeholder'ы, т.к. ADL делает свое дело.
Re[3]: Варим кашу в буст - lambda + bind + shared_ptr
От: ArtDenis Россия  
Дата: 30.08.06 08:16
Оценка: +1
Здравствуйте, AgIle, Вы писали:
AI>Спасибо, можно проще:
AI>...

Но всё равно BOOST_FOREACH проще:
foreach(const boost::shared_ptr<IDownloaderObserver> & item, downloadObservers)
    item->OnCompleted(fileName);

[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[4]: Варим кашу в буст - lambda + bind + shared_ptr
От: Alex Alexandrov США  
Дата: 02.09.06 05:09
Оценка:
Здравствуйте, zaufi, Вы писали:

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


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


Z>>>хинт: в первом случае в векторе лежат _не_указатели_ а _объекты_ shared_ptr из которых еще надо достать указатель и только после этого вызывать евоный OnComplete!

S>>А разве bind сам этого не умеет делать?

Z>а как ты се это преставляешь??


Z>г-н AgIle пытаица заbindить метод IDownloaderObserver'a а for_each упорно пихает в функтор объекты shared_ptr<IDownloaderObserver> -- дело тут совершенно не в bind'e -- товарисча грязно обругивает несогласный (обоснованно) компилятор (который не может вызвать IDownloaderObserver::OnCompleted у shared_ptr'a и пребывает в растерянности от беспардонных действий юзера )


Можно посмотреть как сделать boost/multi_index/mem_fun.hpp для поддержки Chained Pointers.
It's kind of fun to do the impossible (Walt Disney)
Re[5]: Варим кашу в буст - lambda + bind + shared_ptr
От: Alex Alexandrov США  
Дата: 02.09.06 05:12
Оценка:
Здравствуйте, Alex Alexandrov, Вы писали:

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


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


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


Z>>>>хинт: в первом случае в векторе лежат _не_указатели_ а _объекты_ shared_ptr из которых еще надо достать указатель и только после этого вызывать евоный OnComplete!

S>>>А разве bind сам этого не умеет делать?

Z>>а как ты се это преставляешь??


Z>>г-н AgIle пытаица заbindить метод IDownloaderObserver'a а for_each упорно пихает в функтор объекты shared_ptr<IDownloaderObserver> -- дело тут совершенно не в bind'e -- товарисча грязно обругивает несогласный (обоснованно) компилятор (который не может вызвать IDownloaderObserver::OnCompleted у shared_ptr'a и пребывает в растерянности от беспардонных действий юзера )


AA>Можно посмотреть как сделать boost/multi_index/mem_fun.hpp для поддержки Chained Pointers.


Имелось в виду — как сделано в Multi Index. Там экстрактор ключа автоматически применяет -> сколько надо раз.
It's kind of fun to do the impossible (Walt Disney)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.