Boost::bind

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by cupper, 25 Oct 2010.

  1. cupper

    cupper Elder - Старейшина

    Joined:
    6 Jun 2007
    Messages:
    369
    Likes Received:
    92
    Reputations:
    5
    Нихрена понимаю как оно работает
    Вот гигантский ман про это http://www.rsdn.ru/?article/cpp/boost.bind.xml, вот там первый пример
    Code:
    void nine_arguments(
      int i1, int i2, int i3, int i4, 
      int i5, int i6, int i7, int i8, int i9) 
    {
      std::cout << i1 << i2 << i3 << i4 << i5
        << i6 << i7 << i8 << i9 << '\n';
    }
    
    int main() 
    {
      int i1 = 1, i2 = 2, i3 = 3, i4 = 4, i5 = 5, i6 = 6, i7 = 7, i8 = 8, i9 = 9;
      (boost::bind(&nine_arguments, _9, _2, _1, _6, _3, _8, _4, _5, _7))
        (i1, i2, i3, i4, i5, i6, i7, i8, i9);
    }
    
    тут все понятно, за исключением того нахрен это вообще нужно :)
    Вот следующий типо "реальный" пример
    Code:
    class status 
    {
      std::string name_;
      bool ok_;
    
    public:
      status(const std::string& name):name_(name), ok_(true) {}
    
      void break_it() 
      {
        ok_ = false;
      }
    
      bool is_broken() const 
      {
        return ok_;
      }
    
      void report() const 
      {
        std::cout << name_ << " is " 
          << (ok_ ? "working nominally":"terribly broken") << '\n';
      }
    };
    ...
    std::for_each(
      statuses.begin(), 
      statuses.end(), 
      boost::bind(&status::report, _1));
    
    некуя она не ясна и не понятна. Какой еще фактический параметр который должен заменить _1, там же функция передается вообще без аргументов, помогите понять как оно работает, а то в гугле прям перекати поле, как будто это тема избранных и народ пишет либо что нихрена понимает что это такое, либо пишет что все охренено классно, но не кто не пишет простых полезных примеров :(
     
  2. greki_hoy

    greki_hoy Member

    Joined:
    4 Mar 2010
    Messages:
    326
    Likes Received:
    57
    Reputations:
    41
    http://www.rsdn.ru/article/cpp/boost.bind.xml
    Дополнительно о заменителях и аргументах

    Первый пример продемонстрировал, что bind поддерживает до девяти аргументов, а теперь посмотрим поближе на то, как взаимодействуют аргументы и заменители. Прежде всего, нужно обратить внимание, что есть важное различие между свободными функциями и методами: при связывании метода первый аргумент bind должен быть экземпляром класса, в котором определен метод! Если проще, этот явный параметр занимает место неявного this, который передается во все нестатические методы. Прилежный читатель обратит внимание, что на практике это означает, что при связывании методов поддерживаются только (!) восемь параметров, потому что первый будет использован под текущий объект. Следующий пример определяет свободную функцию print_string и класс some_class с методом print_string, с последующим использованием их в bind-выражении:
    Code:
    #include <iostream>
    #include <string>
    #include "boost/bind.hpp"
    
    class some_class 
    {
    public:
      typedef void result_type;
    
      void print_string(const std::string& s) const 
      {
        std::cout << s << '\n';
      }
    };
    
    void print_string(const std::string s) 
    {
      std::cout << s << '\n';
    }
    
    int main() 
    {
      (boost::bind(&print_string, _1))("Hello func!");
      some_class sc;
      (boost::bind(&some_class::print_string, _1, _2))
        (sc, "Hello member!");
    }
    
     
    #2 greki_hoy, 25 Oct 2010
    Last edited: 26 Oct 2010
    2 people like this.
  3. cupper

    cupper Elder - Старейшина

    Joined:
    6 Jun 2007
    Messages:
    369
    Likes Received:
    92
    Reputations:
    5
    это было весьма нелепо давать мне в ответ ссылку которую я написал в первом посте и сказал что мне от туда непонятный примеры :)
    Незнаю понимаешь ли ты сам то что скопипастил или нет, но вопросы все равно остались.
    Когда идет вызов обычной "свободной" функции, таким образом
    Code:
    (boost::bind(&print_string, _1))("Hello func!");
    
    то тут все понятно. Непонятно зачем только оно нужно :) Но это видно пример показывающий типо "а мы и вот так умеем".
    Другое дело когда это выглядит например так
    Code:
    void print(const boost::system::error_code& /*e*/,
        boost::asio::deadline_timer* t, int* count)
    {...}
    t->async_wait(boost::bind(print,
              boost::asio::placeholders::error, t, count));
    
    тут вроде как все понятно, функция async_wait принимает call-back функцию определенной сигнатуры void f(onst boost::system::error_code&) и бинд нам как раз помогает функцию от нескольких переменных превратить в некий "функтор" который имеет подходящую сигнатуру.

    Следущее вызов, и небольшое набор слов который написал greki_hoy
    Code:
    (boost::bind(&some_class::print_string, _1, _2))
        (sc, "Hello member!");
    
    объяснил мне тот факт что в случаем если функция это member класса, то тогда нужно чтобы на месте _1 передавался экземпляр класс, теперь понятно и такое например
    Code:
    timer_.async_wait(boost::bind(&printer::print, this));
    
    ...
    AAaaaaaaaaa :)
    Теперь понятен и ключевой вопрос
    Code:
    std::for_each(
      statuses.begin(), 
      statuses.end(), 
      boost::bind(&status::report, _1));
    
    в функции for_each вместо _1 будет подставляться текущий класс, и для него будет вызываться &status::report... ух как оно все запутанно было :)

    Спасибо greki_hoy :)