【问题标题】:boost::ref and boost::asio completion handlers, pass-by-referenceboost::ref 和 boost::asio 完成处理程序,按引用传递
【发布时间】:2011-09-02 11:40:55
【问题描述】:
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。所以我想我在这里不走运。处理程序没有接受 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;
  };

} }

【问题讨论】:

  • 你能展示一下i 的样子吗?
  • 你要求的 :D 基类有三个 ptr 和访问器。
  • 我实际上是指定义。 :) i 需要是一个处理程序,boost::ref 只给你一个没有operator() 的包装器。

标签: c++ functional-programming pass-by-reference boost-asio boost-ref


【解决方案1】:

boost::ref 不提供operator() 的重载。因此,返回不能直接用作回调。有两种选择:

  1. C++03: 使用boost::bind 包装 ref,它会做你想做的事

    m_io_service.post(boost::bind&lt;ReturnType&gt;(boost::ref(i)))

    请注意,您必须指定返回类型,除非原始函子 i 具有 result_type 的 typedef

  2. C++11:改用std::ref,它确实提供了一个operator(),它传递到所包含的引用

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

【讨论】:

  • 这是正确的。 boost::ref 不提供 operator(),这是错误消息所说的。 asio::post 需要一个处理程序(函数)来调用。
  • 是的,但是库实现者为模板 boost::reference_wrapper&lt;T&gt; 提供重载(用于异步调度调用)不是谨慎的做法吗?为了弥补缺少的话务员,只是好奇而已。我可能会去std::ref:D 谢谢。
  • 好吧,问题是每个接受函子的库编写者都必须将boost::reference_wrapper&lt;T&gt; 重载(这是bind 所做的)添加到他们可能的函子集中。由于 ASIO 可以在非 boost 风格中找到,因此为特定于 boost 的包装器添加额外的重载似乎是错误的方法。另一方面,让boost::ref 的用户使用boost::bind 对于库开发人员来说工作量更少,所以他们采用了这种方法。
  • boost::bind 似乎是最干净的可移植方式。在库最终确定之前,std::ref 仍处于不确定状态。
【解决方案2】:

似乎boost::ref 不适合这种用途。 boost::ref 提供了包装器,因此值得怀疑的是,通过值传递还是通过 boost::ref 传递更有效,主要取决于您的可调用对象复制构造函数。作为一种解决方法,您可以使用boost::bind:

m_io_service.post(boost::bind(&Callable::operator(), &i));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 2016-12-22
    • 1970-01-01
    相关资源
    最近更新 更多