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 варианта:
C++ 03: использовать
boost::bind
обернуть ссылку, и она будет делать то, что вы хотитеm_io_service.post(boost::bind<ReturnType>(boost::ref(i)))
Обратите внимание, что вы должны указать тип возвращаемого значения, если только оригинальный функтор
i
имеет typedef дляresult_type
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));