boost::bind & const object

Тема в разделе "LANGS.C", создана пользователем systemio, 2 фев 2009.

  1. systemio

    systemio New Member

    Публикаций:
    0
    Регистрация:
    18 мар 2008
    Сообщения:
    98
    есть обычная структура:
    struct sS
    {
    bool is(void) { return false; }
    };

    и код:
    std::vector<const sS*>::iterator i;
    i = std::find_if(i, i, boost::bind(sS::is, _1));

    выдает ошибку компиляции - ругается на const в векторе:
    f:\Boost\include\boost-1_33_1\boost\bind\mem_fn_template.hpp(36): error C2440: 'argument' : cannot convert from 'const sS *' to 'sS *const '

    Компилятор от VS2003.
    Плиз Хелп!
     
  2. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    systemio
    Код (Text):
    1.   struct sS
    2.   {
    3.     bool is(void) const{ return false; }
    4.   };
    5.  
    6. int main(int argc, char **argv)
    7. {
    8.     std::vector<const sS*>::iterator i;
    9.     i = std::find_if(i, i, boost::bind(&sS::is, _1));
    10.      
    11.        return 0;
    12. }
    компилер g++
     
  3. systemio

    systemio New Member

    Публикаций:
    0
    Регистрация:
    18 мар 2008
    Сообщения:
    98
    struct sS
    {
    bool is(void) { return false; }
    const bool is(void) const { return false; }
    };

    Да! У метода is забыл вконце const.
    Но опять не компилится если сделать два одинаковых метода (не смотрите что глупые методы - они повторяют аналогию методов begin для итераторов).
     
  4. systemio

    systemio New Member

    Публикаций:
    0
    Регистрация:
    18 мар 2008
    Сообщения:
    98
    Отбой! Нашел!

    typedef const bool (sS::*pMF)(void) const;
    pMF p = sS::is;
    i = std::find_if(i, i, boost::bind(p, _1));
     
  5. s0larian

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    systemio, вот тебе три формы - boost headers сами определяют тип:
    Код (Text):
    1.     std::vector<Something> v;
    2.     std::vector<Something>::iterator i =
    3.         std::find_if(v.begin(),
    4.              v.end(),
    5.              boost::bind(&Something::is, _1));
    6.  
    7.     std::vector<Something *> vp;
    8.     std::vector<Something *>::iterator j =
    9.         std::find_if(vp.begin(),
    10.              vp.end(),
    11.              boost::bind(&Something::is, _1));
    12.  
    13.     std::vector<const Something *> vpc;
    14.     std::vector<const Something *>::iterator k =
    15.         std::find_if(vpc.begin(),
    16.              vpc.end(),
    17.              boost::bind(&Something::is, _1));
    ессно, для "bool is() const {return false;}"

    кста, для references есть boost:ref(_1) и boost::cref(_1)
     
  6. systemio

    systemio New Member

    Публикаций:
    0
    Регистрация:
    18 мар 2008
    Сообщения:
    98
    при наличии структуры вида:
    struct sS
    {
    bool is(void) { return false; }
    const bool is(void) const { return false; }
    };

    ни одна из записей не работает:
    boost::bind(&sS::is, boost::cref(_1))
    boost::bind(&sS::is, boost::ref(_1))

    Я думаю он не может распарсить и ему приходится вручную указывать верный вариант. Непонятно!!!
    Это конечно огорчает - кажется это единственный выход в такой ситуации.
     
  7. s0larian

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    systemio, что-то ты путаешь. Выше я привёл рабочий код для разных контейнеров - скомпилено в VS2008. Твой случай - последний.

    Про boost::ref() - во-первых это не твой случай т.к. у тебя указатели. А во-вторых, я чуть приврал - это надо что бы послать аргумент типа reference в сгенерированный functor:

    Код (Text):
    1. void CalcThread::NotifyOnFinish(bool valid,
    2.                                 const Result &r, const base::String &output)
    3. {
    4.     std::for_each(m_ovservers_.begin(), m_ovservers.end(),
    5.         boost::bind(&StatusHandler::OnFinish, _1, valid, boost::ref(r), boost::ref(output)));
    6. }
     
  8. systemio

    systemio New Member

    Публикаций:
    0
    Регистрация:
    18 мар 2008
    Сообщения:
    98
    std::find_if(i, i, boost::bind(&sS::is, _1)) - вот эта штука не компилится потому что компилятор (у меня ВС 2003) не может определить какую из двух is выбрать. Вернее он выбирает не константный метод и у него не стыкуется с константным объектом. поэтому приходися вручную делать указатель на константный метод и подсовывать в bind. Такие дела!
     
  9. s0larian

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    так оставь только константную версию метода. Не-конст через "const указатель" компилер ессно не даст вызвать.

    Не понимаю в чём проблема.

    Кста, убери тот "const" что вначале - для bool это бессмысленно.