Я хотел бы создать оболочку, чтобы упростить запись привязок для обработчиков, чтобы мне просто нужно было передать обратный вызов и указатель данных.

Это мой код:

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

Но у меня проблемы с обработкой специализации для последнего случая ...

1
hl037_ 7 Сен 2016 в 17:10

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};
}

Эх вуаля.

1
Barry 7 Сен 2016 в 14:29

С ++ 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); }));
0
Richard Hodges 7 Сен 2016 в 14:15

Самым простым было бы просто использовать лямбду:

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)...);
}
0
Barry 7 Сен 2016 в 14:20