boost::ref и boost::asio - обработчики завершения, передача по ссылке

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 ответа

Решение

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))

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

m_io_service.post(boost::bind(&Callable::operator(), &i));
Другие вопросы по тегам