boost :: ref и boost :: asio - обработчики завершения, передача по ссылке - PullRequest
4 голосов
/ 02 сентября 2011
m_io_service.post(boost::ref(i));

У меня есть этот вызов в разделе кода, базовый тип i определенно вызывается (потому что удаление boost :: ref приводит к передаче по значению, что прекрасно работает), однако clang говорит мне, что:

/opt/dev_64_swat/proto-rpc2/dependencies/boost/include/boost/asio/handler_invoke_hook.hpp:64:3: error: type 'boost::reference_wrapper<rubble::rpc::TcpFrontEndConnectionInvoker>' does not provide a call operator

Как мне передать по ссылке, у меня есть объекты, которые переживают асинхронные вызовы, и они были бы более элегантными (за исключением элементов boost :: shared_ptr <..>), если бы я мог передавать их по ссылке.

- редактировать -

Я пролистал пример каталога asio, и boost::ref не показывается для обработчиков завершения. Так что, думаю, мне здесь не повезло. Есть ли причина, по которой у обработчиков нет версии, принимающей ссылки?

- редактировать 2: как я выгляжу (не беспокойтесь об этом, если вы не подозреваете о реализации). -

namespace rubble { namespace rpc {
  struct InProcessInvoker : public InvokerBase
  {
    struct notification_object_
    {
      typedef notification_object_ * ptr;

      notification_object_()
      {
        reset();
      }
      void reset()
      {
        ready = false;
      }
      bool ready;
      boost::mutex mutex;
      boost::condition_variable cond;
    };

    InProcessInvoker(BackEnd & b_in)
      : b(b_in),
        notification_object(new notification_object_())
    {
      b.connect(m_client_data);
    }

    ~InProcessInvoker()
    {
      if( m_client_data.unique() )
      {
        b.disconect(m_client_data);
        delete notification_object;
      }
    }

    bool is_useable()
    {
      return b.is_useable();
    }

    void reset()
    {
      notification_object->reset();
      m_client_data->request().Clear();
      m_client_data->response().Clear();
      m_client_data->error_code().clear();
      BOOST_ASSERT_MSG( m_client_data->is_rpc_active() == false,
        "THE FLAG THAT REPRESENTS ACTIVE "
        "RPC SHOULD NOT BE SET WHEN RESETING AN OBJECT FOR RPC");
    }

    void invoke()
    {
      b.invoke(*this);
    }

    void operator() ()
    {
      service->dispatch(*client_cookie,*m_client_data);
      b.end_rpc(m_client_data.get());

      boost::lock_guard<boost::mutex> lock(notification_object->mutex);
      notification_object->ready=true;
      notification_object->cond.notify_one();
    }

    void after_post()
    {
      boost::unique_lock<boost::mutex> lock(notification_object->mutex);
      if(!notification_object->ready)
        notification_object->cond.wait(lock);
    }

    notification_object_::ptr notification_object;
    BackEnd & b;
  };

} }

Ответы [ 2 ]

6 голосов
/ 02 сентября 2011

boost::ref не обеспечивает перегрузки operator(). Следовательно, возврат не может быть использован напрямую как обратный вызов. Есть 2 варианта:

  1. C ++ 03: используйте boost::bind, чтобы обернуть ссылку, и она будет делать то, что вы хотите

    m_io_service.post(boost::bind<ReturnType>(boost::ref(i)))

    Обратите внимание, что вы должны указать тип возвращаемого значения, если только исходный функтор i не имеет typedef для result_type

  2. C ++ 11: используйте взамен std::ref, который предоставляет оператор (), который проходит к содержащейся ссылке

    m_io_service.post(std::ref(i))

2 голосов
/ 02 сентября 2011

Кажется boost::ref не предназначен для такого использования.boost::ref предоставляет оболочку, поэтому сомнительно, что было бы более эффективно, передавать по значению или boost::ref, в основном зависит от вашего конструктора копирования вызываемого объекта.В качестве обходного пути вы можете использовать boost::bind:

m_io_service.post(boost::bind(&Callable::operator(), &i));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...