Проблема с std::mem_fun
От: PM  
Дата: 01.08.03 12:26
Оценка:
Что-то торможу под конец дня. Есть такое:
class foo;
typedef boost::shared_ptr<foo> foo_ptr;

class bar;
typedef boost::shared_ptr<bar> bar_ptr;

class bar
{
public:
    void f(foo_ptr pfoo);
};

class foo
{
    vector<bar_ptr> bars_;
    void g()
    {
        for_each( bars_.begin(), bars_.end(),
                    bind2nd(
                        mem_fun<void, bar_ptr, foo_ptr>(&bar::f),
                        foo_ptr(this) 
                    )
                );
    }
};

Не компилируется — типы bar_ptr и bar для mem_fun не совпадают.

Пытаюсь сделать
        for_each( bars_.begin(), bars_.end(),
                    bind2nd(
                        mem_fun<void, bar, foo_ptr>(&bar::f),
                        foo_ptr(this) 
                    )
                );

Тоже не компилируется — теперь не совпадают типы аргументов для bind2nd.

Есть ли какое-то решение, кроме написания своего функтора?
Posted via RSDN NNTP Server 1.7 beta
Re: Проблема с std::mem_fun
От: Анатолий Широков СССР  
Дата: 01.08.03 13:52
Оценка: 5 (1)
Если бы существовал оператор приведения из boo_ptr в boo*, то можно было бы ограничиться следующим:

...
class foo
{
    std::vector<bar_ptr> bars_;
    void g()
    {
        std::for_each( bars_.begin(), bars_.end(),
                    std::bind2nd(
                        std::mem_fun(&bar::f),                        
                           foo_ptr(this) 
                    )
                );
    }
};


Ну, а так необходим конвертор:

...
template<typename T>
struct smart2ptr_t
{
    T f;

    smart2ptr_t(T t) : f(t) {}

    template<typename R>
    void operator()(R &p)
    {
        f(p.get());
    }
};

template<typename T>
smart2ptr_t<T> smart2ptr(T op)
{
    return smart2ptr<T>(op);
}

class foo
{
    std::vector<bar_ptr> bars_;
    void g()
    {
        std::for_each( bars_.begin(), bars_.end(),
               smart2ptr(    
                      std::bind2nd(
                        std::mem_fun(&bar::f),                             
                           foo_ptr(this) 
                    )
              )
        );
    }
};


Удачи.
Re: Проблема с std::mem_fun
От: Юнусов Булат Россия  
Дата: 01.08.03 14:09
Оценка: 16 (2)
Здравствуйте, PM, Вы писали:


    foo_ptr(this)

Низзя же так, чревато, разве что метод f() вызывается только один раз обьектом созданным в хипе, иначе кырдык.


Если уж используешь shared_ptr то лучше использовать и бустовые биндеры.
Re: Проблема с std::mem_fun
От: limax Россия http://mem.ee
Дата: 01.08.03 14:26
Оценка: 5 (1)
Здравствуйте, PM, Вы писали:

Во-первых, почему все ещё пользуются устаревшими std:: классами? Используешь shared_ptr из boost-а, а bind — не хочешь. Про lambda умолчу, т.к. хоть и удобная, да не все компилеры ещё доросли.
Во-вторых, создавать foo_ptr(this) — равноценно самоуничтожению.
А так...
http://www.boost.org/libs/bind/bind.html#with_member_pointers
    void g()
    {
        std::for_each( bars_.begin(), bars_.end(), bind(&bar::f, _1, some_foo_ptr));
    }
Have fun: Win+M, Ctrl+A, Enter
Re[2]: Проблема с std::mem_fun
От: Анатолий Широков СССР  
Дата: 01.08.03 14:31
Оценка:
Здравствуйте, limax, Вы писали:

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


L>Во-первых, почему все ещё пользуются устаревшими std:: классами?


А кто их устарел?

L>    void g()
L>    {
L>        std::for_each( bars_.begin(), bars_.end(), bind(&bar::f, _1, some_foo_ptr));
L>    }
L>


А может вы представите рабочий пример?
Re[3]: Проблема с std::mem_fun
От: limax Россия http://mem.ee
Дата: 02.08.03 10:40
Оценка: +1
Здравствуйте, Анатолий Широков, Вы писали:

L>>Во-первых, почему все ещё пользуются устаревшими std:: классами?

АШ>А кто их устарел?
Никто, просто не зря в буст были добавлены более удобные аналоги. Тем более, что со многими бустовыми классами стандартные уже работают.

АШ>
L>>    void g()
L>>    {
L>>        std::for_each( bars_.begin(), bars_.end(), bind(&bar::f, _1, some_foo_ptr));
L>>    }
L>>

АШ>А может вы представите рабочий пример?
А этот разве не работает???
some_foo_ptr — это foo_ptr указывающий на this. Откуда его брать — это уже дело автора топика, т.к. тривиально эта проблема не решается, однако можно воспользоваться enable_shared_from_this. См. здесь и здесь
Have fun: Win+M, Ctrl+A, Enter
Re[4]: Проблема с std::mem_fun
От: Анатолий Широков СССР  
Дата: 02.08.03 12:37
Оценка:
Здравствуйте, limax, Вы писали:

L>Здравствуйте, Анатолий Широков, Вы писали:


L>>>Во-первых, почему все ещё пользуются устаревшими std:: классами?

АШ>>А кто их устарел?
L>Никто, просто не зря в буст были добавлены более удобные аналоги. Тем более, что со многими бустовыми классами стандартные уже работают.

АШ>>
L>>>    void g()
L>>>    {
L>>>        std::for_each( bars_.begin(), bars_.end(), bind(&bar::f, _1, some_foo_ptr));
L>>>    }
L>>>

АШ>>А может вы представите рабочий пример?
L>А этот разве не работает???

Нет, и даже если изменить сигнатуру на void boo::f(foo *) и передавать вместо some_foo_ptr this. В чем была проблема я осветил в своем посте.
Re[5]: Проблема с std::mem_fun
От: Юнусов Булат Россия  
Дата: 02.08.03 18:58
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

L>>А этот разве не работает???


АШ>Нет, и даже если изменить сигнатуру на void boo::f(foo *) и передавать вместо some_foo_ptr this. В чем была проблема я осветил в своем посте.


Работает оно, и с такой сигнатурой и с сякой.
Мне кажется ты немножко поторопился
Re[2]: Проблема с std::mem_fun
От: Аноним  
Дата: 03.08.03 15:27
Оценка:
Здравствуйте, limax,

Мне просто любопытно, а есть ли у boost::bind1st, boost::bind2nd и пр. преемущества перед boost::bind?
Re[3]: Проблема с std::mem_fun
От: ArtDenis Россия  
Дата: 03.08.03 15:33
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Здравствуйте, limax,


А>Мне просто любопытно, а есть ли у boost::bind1st, boost::bind2nd и пр. преемущества перед boost::bind?


У них два приемущества — скорость и стандарт.

Денис.
... << RSDN@Home 1.1 beta 1 >>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[4]: Проблема с std::mem_fun
От: skyline Россия  
Дата: 03.08.03 15:36
Оценка:
Здравствуйте, ArtDenis

Какой стандарт? Разве они предусмотренны стандартом?
If the milk turns out to be sour,
I ain't the kind of pussy to drink it
Re[5]: Проблема с std::mem_fun
От: ArtDenis Россия  
Дата: 03.08.03 15:43
Оценка:
Здравствуйте, skyline, Вы писали:

S>Здравствуйте, ArtDenis


S>Какой стандарт? Разве они предусмотренны стандартом?


Блин, прочитал вопрос как std::bind1st, std::bind2nd . Сорри
... << RSDN@Home 1.1 beta 1 >>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[2]: Проблема с std::mem_fun
От: PM  
Дата: 04.08.03 06:49
Оценка:
Здраствуйте, Юнусов Булат. Вы писали:

ЮБ> Здравствуйте, PM, Вы писали:

ЮБ>
ЮБ>
 ЮБ>     foo_ptr(this)
 ЮБ>

ЮБ> Низзя же так, чревато, разве что метод f() вызывается только один раз
ЮБ> обьектом созданным в хипе, иначе кырдык.

Спасибо, действительно, так могут быть глюки

ЮБ> Если уж используешь shared_ptr то лучше использовать и бустовые биндеры.
Posted via RSDN NNTP Server 1.7 beta
Re[6]: Проблема с std::mem_fun
От: PM  
Дата: 04.08.03 07:16
Оценка:
Здраствуйте, Юнусов Булат. Вы писали:

L>>> А этот разве не работает???

ЮБ>
АШ>> Нет, и даже если изменить сигнатуру на void boo::f(foo *) и передавать
АШ>> вместо some_foo_ptr this. В чем была проблема я осветил в своем посте.
ЮБ>
ЮБ> Работает оно, и с такой сигнатурой и с сякой. Мне кажется ты немножко поторопился
ЮБ>
У меня 7-й интел не компилирует. Как верно заметил Анатолий, из-за отсутствия преобразования bar_ptr в bar*
Буду писать функтор
Posted via RSDN NNTP Server 1.7 beta
Re[7]: Проблема с std::mem_fun
От: Юнусов Булат Россия  
Дата: 04.08.03 08:56
Оценка:
Здравствуйте, PM, Вы писали:

PM>У меня 7-й интел не компилирует. Как верно заметил Анатолий, из-за отсутствия преобразования bar_ptr в bar*

PM>Буду писать функтор

Странно, vc6.0 vc7.1 gcc3.3 съели нормально, неужели интел не разруливает?


#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <vector>
#include <algorithm>
#include <iostream>

class foo;
typedef boost::shared_ptr<foo> foo_ptr;

class bar;
typedef boost::shared_ptr<bar> bar_ptr;

class bar
{
public:
    void f(foo_ptr p) {
        std::cout << "bar::f(foo_ptr p)" << std::endl;
    }
    void f1(foo * p) const {
        std::cout << "bar::f(foo * p)" << std::endl;
    }
};

class foo : public boost::enable_shared_from_this<foo>
{
public:
    foo() {
        bars_.push_back(bar_ptr(new bar));
    }

    void g() {
        std::for_each( bars_.begin(), bars_.end(),
            boost::bind(&bar::f, _1, shared_from_this())
            );

        std::for_each( bars_.begin(), bars_.end(),
            boost::bind(&bar::f1, _1, this )
            );
    }

    std::vector<bar_ptr> bars_;
};

int main(int argc, char* argv[])
{
    foo_ptr p(new foo);
    p->g();

    return 0;
}
Re[8]: Проблема с std::mem_fun
От: PM  
Дата: 04.08.03 13:17
Оценка:
Здраствуйте, Юнусов Булат. Вы писали:

[]
Спасибо, все заработало, это у меня от экспериментов оставались левые куски. Пора в отпуск
Posted via RSDN NNTP Server 1.7 beta
Re[4]: Проблема с std::mem_fun
От: limax Россия http://mem.ee
Дата: 05.08.03 13:39
Оценка:
Тьфу, опечатался с точностью до наоборот.
L>Тем более, что со многими бустовыми классами стандартные уже не работают.
Have fun: Win+M, Ctrl+A, Enter
Re[3]: Проблема с std::mem_fun
От: limax Россия http://mem.ee
Дата: 05.08.03 13:57
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Мне просто любопытно, а есть ли у boost::bind1st, boost::bind2nd и пр. преемущества перед boost::bind?
Ы?
А где ты их вообще нашёл?
В 1.30.0 я их не нашёл, по крайней мере в документации. А если где-то и есть, то оставлены только для совместимости с левыми компиляторами и старыми версиями boost.

А если ты ошибся и имел в виду std::bind1st/bind2nd, то, при условии, что компилятор нормально понимает boost::bind:
  • в плане функциональности и удобства использования они на-амного проигрывают boost::bind;
  • в плане скорости и размера генерируемого кода они равны;
  • в плане стандарта... Хм, я думаю любой, кто интересуется такой функциональностью STL, как биндинг аргументов, имеет у себя установленный boost или хоть раз им пользовался. А если нет, то никогда не поздно это сделать.
  • Have fun: Win+M, Ctrl+A, Enter
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.