Я хотел бы создать оболочку, чтобы упростить запись привязок для обработчиков, чтобы мне просто нужно было передать обратный вызов и указатель данных.
Это мой код:
#include <utility>
template <typename Func, typename Data>
class Handler
{
const Func & m_func;
volatile Data & m_data;
public:
Handler(const Func & f, Data & d) :
m_func(f),
m_data(d)
{}
Handler(const Handler & cpy) :
m_func(cpy.m_func),
m_data(cpy.m_data)
{}
template<typename Res=void, typename... Args>
Res operator()(Args... args) const
{
return m_func(m_data, std::forward<Args>(args)... );
}
};
/* I need help to handle this specialization */
template<typename T>
template<typename Res=void, typename... Args>
Res Handler<(T::*)(Args...), T*>::operator()(Args... args) const
{
return (m_data->*m_func)(std::forward<Args>(args)... );
}
template <typename Func, typename Data>
inline Handler<Func, Data> handler(Func f, Data d)
{
return Handler<Func, Data>(f, d);
}
Цель состоит в следующем:
boost::asio::async_read(socket,
boost::asio::buffer(d, n),
handler(callback, session)
);
Или вот так:
boost::asio::async_read(socket,
boost::asio::buffer(d, n),
handler(&Object::method, this_ptr)
);
Но у меня проблемы с обработкой специализации для последнего случая ...
3 ответа
Неожиданный сбой задачи «DeleteCurrentDeployment». System.IO.FileNotFoundException: не удалось загрузить файл или сборку Microsoft.ServiceHosting.Tools, Version = 1.0.0.0, Culture = нейтральный, PublicKeyToken = 31bf3856ad364e35 или одну из его зависимостей. Система не может найти указанный файл. Имя файла: 'Microsoft.ServiceHosting.Tools, Version = 1.0.0.0, Culture = нейтральный, PublicKeyToken = 31bf3856ad364e35' в Microsoft.Cct.Debugging.DevFabricService..ctor () в Microsoft.Cct. CctProjectNode. <> C.b__121_0 () в System.Threading.LazyInitializer.EnsureInitializedCore [T] (T & target, Func handler()
1 valueFactory) в Microsoft.Cct.CctProjectNode.get_DevFabricService () в Microsoft.CctostD.Cep DeleteCurrentDeployment () в Microsoft.CloudExtensions.MSBuildTasks.DeleteCurrentDeployment.Execute () в Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Exovecute () в Microsoft.Build__BackEnd.No. : Ведение журнала привязки сборки отключено. Чтобы включить ведение журнала сбоев привязки сборки, установите для параметра реестра [HKLM \ Software \ Microsoft \ Fusion! EnableLog] (DWORD) значение 1. Примечание. Ведение журнала сбоев привязки сборки приводит к некоторому снижению производительности. Чтобы отключить эту функцию, удалите Проверьте значение реестра [HKLM \ Software \ Microsoft \ Fusion! EnableLog].…
template <typename Func, typename Data>
struct Handler
{
Func func; // NB: not a reference
Data data;
template<class... Args>
auto operator()(Args&&... args) const // NB: this wasn't a forwarding ref before
-> decltype(func(data, std::forward<Args>(args)...))
{
return func(data, std::forward<Args>(args)... );
}
};
Неожиданный сбой задачи «DeleteCurrentDeployment». System.IO.FileNotFoundException: не удалось загрузить файл или сборку Microsoft.ServiceHosting.Tools, Version = 1.0.0.0, Culture = нейтральный, PublicKeyToken = 31bf3856ad364e35 или одну из его зависимостей. Система не может найти указанный файл. Имя файла: 'Microsoft.ServiceHosting.Tools, Version = 1.0.0.0, Culture = нейтральный, PublicKeyToken = 31bf3856ad364e35' в Microsoft.Cct.Debugging.DevFabricService..ctor () в Microsoft.Cct. CctProjectNode. <> C.b__121_0 () в System.Threading.LazyInitializer.EnsureInitializedCore [T] (T & target, Func Handler
1 valueFactory) в Microsoft.Cct.CctProjectNode.get_DevFabricService () в Microsoft.CctostD.Cep DeleteCurrentDeployment () в Microsoft.CloudExtensions.MSBuildTasks.DeleteCurrentDeployment.Execute () в Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Exovecute () в Microsoft.Build__BackEnd.No. : Ведение журнала привязки сборки отключено. Чтобы включить ведение журнала сбоев привязки сборки, установите для параметра реестра [HKLM \ Software \ Microsoft \ Fusion! EnableLog] (DWORD) значение 1. Примечание. Ведение журнала сбоев привязки сборки приводит к некоторому снижению производительности. Чтобы отключить эту функцию, удалите Проверьте значение реестра [HKLM \ Software \ Microsoft \ Fusion! EnableLog].…
Теперь мы можем написать нашу функцию:
template <class F, class D>
Handler<std::decay_t<F>, std::decay_t<D>> handler(F&& f, D&& d) {
return {std::forward<F>(f), std::forward<D>(d)};
}
Неожиданный сбой задачи «DeleteCurrentDeployment». System.IO.FileNotFoundException: не удалось загрузить файл или сборку Microsoft.ServiceHosting.Tools, Version = 1.0.0.0, Culture = нейтральный, PublicKeyToken = 31bf3856ad364e35 или одну из его зависимостей. Система не может найти указанный файл. Имя файла: 'Microsoft.ServiceHosting.Tools, Version = 1.0.0.0, Culture = нейтральный, PublicKeyToken = 31bf3856ad364e35' в Microsoft.Cct.Debugging.DevFabricService..ctor () в Microsoft.Cct. CctProjectNode. <> C.b__121_0 () в System.Threading.LazyInitializer.EnsureInitializedCore [T] (T & target, Func handler
1 valueFactory) в Microsoft.Cct.CctProjectNode.get_DevFabricService () в Microsoft.CctostD.Cep DeleteCurrentDeployment () в Microsoft.CloudExtensions.MSBuildTasks.DeleteCurrentDeployment.Execute () в Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Exovecute () в Microsoft.Build__BackEnd.No. : Ведение журнала привязки сборки отключено. Чтобы включить ведение журнала сбоев привязки сборки, установите для параметра реестра [HKLM \ Software \ Microsoft \ Fusion! EnableLog] (DWORD) значение 1. Примечание. Ведение журнала сбоев привязки сборки приводит к некоторому снижению производительности. Чтобы отключить эту функцию, удалите Проверьте значение реестра [HKLM \ Software \ Microsoft \ Fusion! EnableLog].…
template <class R, class T>
auto handler(R T::* p, T* cls)
-> Handler<decltype(std::mem_fn(p)), T*>
{
return {std::mem_fn(p), cls};
}
Эх вуаля.
С ++ 11:
boost::asio::async_read(socket,
boost::asio::buffer(d, n),
[this](boost::system::error_code const& ec, std::size_t transferred)
{ this->method(ec, transferred); });
С ++ 14:
boost::asio::async_read(socket,
boost::asio::buffer(d, n),
[this](auto const& ec, auto transferred)
{ this->method(ec, transferred); });
Лямбды - прекрасные асинхронные обработчики в asio.
Также они работают с прядями и т. Д .:
boost::asio::async_read(socket,
boost::asio::buffer(d, n),
this->strand_.wrap([this](auto const& ec, auto transferred)
{ this->method(ec, transferred); }));
Неожиданный сбой задачи «DeleteCurrentDeployment». System.IO.FileNotFoundException: не удалось загрузить файл или сборку Microsoft.ServiceHosting.Tools, Version = 1.0.0.0, Culture = нейтральный, PublicKeyToken = 31bf3856ad364e35 или одну из его зависимостей. Система не может найти указанный файл. Имя файла: 'Microsoft.ServiceHosting.Tools, Version = 1.0.0.0, Culture = нейтральный, PublicKeyToken = 31bf3856ad364e35' в Microsoft.Cct.Debugging.DevFabricService..ctor () в Microsoft.Cct. CctProjectNode. <> C.b__121_0 () в System.Threading.LazyInitializer.EnsureInitializedCore [T] (T & target, Func shared_from_this()
1 valueFactory) в Microsoft.Cct.CctProjectNode.get_DevFabricService () в Microsoft.CctostD.Cep DeleteCurrentDeployment () в Microsoft.CloudExtensions.MSBuildTasks.DeleteCurrentDeployment.Execute () в Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Exovecute () в Microsoft.Build__BackEnd.No. : Ведение журнала привязки сборки отключено. Чтобы включить ведение журнала сбоев привязки сборки, установите для параметра реестра [HKLM \ Software \ Microsoft \ Fusion! EnableLog] (DWORD) значение 1. Примечание. Ведение журнала сбоев привязки сборки приводит к некоторому снижению производительности. Чтобы отключить эту функцию, удалите Проверьте значение реестра [HKLM \ Software \ Microsoft \ Fusion! EnableLog].…
boost::asio::async_read(socket,
boost::asio::buffer(d, n),
this->strand_.wrap([self = this->shared_from_this()]
(auto const& ec, auto transferred)
{ self->method(ec, transferred); }));
Самым простым было бы просто использовать лямбду:
boost::asio::async_read(socket,
boost::asio::buffer(d, n),
[&](boost::system::error_code const& ec, size_t transferred) {
// either it's a free function
return callback(session, ec, transferred);
// or it's a member function
return session.member(ec, transferred);
}
);
Неожиданный сбой задачи «DeleteCurrentDeployment». System.IO.FileNotFoundException: не удалось загрузить файл или сборку Microsoft.ServiceHosting.Tools, Version = 1.0.0.0, Culture = нейтральный, PublicKeyToken = 31bf3856ad364e35 или одну из его зависимостей. Система не может найти указанный файл. Имя файла: 'Microsoft.ServiceHosting.Tools, Version = 1.0.0.0, Culture = нейтральный, PublicKeyToken = 31bf3856ad364e35' в Microsoft.Cct.Debugging.DevFabricService..ctor () в Microsoft.Cct. CctProjectNode. <> C.b__121_0 () в System.Threading.LazyInitializer.EnsureInitializedCore [T] (T & target, Func std::invoke()
1 valueFactory) в Microsoft.Cct.CctProjectNode.get_DevFabricService () в Microsoft.CctostD.Cep DeleteCurrentDeployment () в Microsoft.CloudExtensions.MSBuildTasks.DeleteCurrentDeployment.Execute () в Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Exovecute () в Microsoft.Build__BackEnd.No. : Ведение журнала привязки сборки отключено. Чтобы включить ведение журнала сбоев привязки сборки, установите для параметра реестра [HKLM \ Software \ Microsoft \ Fusion! EnableLog] (DWORD) значение 1. Примечание. Ведение журнала сбоев привязки сборки приводит к некоторому снижению производительности. Чтобы отключить эту функцию, удалите Проверьте значение реестра [HKLM \ Software \ Microsoft \ Fusion! EnableLog].…
boost::asio::async_read(socket,
boost::asio::buffer(d, n),
[&](auto&&... args) -> decltype(std::invoke(callback, session, decltype(args)(args)...)) {
return std::invoke(callback, session, decltype(args)(args)...);
}
);
Или, если вы всегда знаете, является ли обратный вызов указателем на функцию-член или нет, вы можете просто использовать правильный, будь то:
[&](auto&&... args) -> decltype(callback(session, decltype(args)(args)...)) {
return callback(session, decltype(args)(args)...);
}
Или же:
[&](auto&&... args) -> decltype(session.member(decltype(args)(args)...)) {
return session.member(decltype(args)(args)...);
}
Похожие вопросы
Новые вопросы
c++
C++ — это язык программирования общего назначения. Изначально он разрабатывался как расширение C и имел аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде, который будет скомпилирован с помощью компилятора C++. Используйте тег версии для вопросов, связанных с конкретной стандартной версией [C++11], [C++14], [C++17], [C++20] или [C++23]. и т.д.