智能指针作为使用 std::function、std::bind 的函数的参数

smart pointer as argument of function which uses std::function, std::bind

#include <functional>
#include <iostream>
#include <memory>

template <typename T>
struct Message
{
    T a;
};

template <typename T>
class Connection : public std::enable_shared_from_this<T>
{
  typedef std::function<void(Message<T>&)> msg_handle;
  public:
    void SetHandle(msg_handle handle)
    {
      handle_ = handle;
    }
    void Run()
    {
      Message<T> t;
      std::cout << "Run() from Connection" << std::endl;
      handle_(t);
    }

  private:
    msg_handle handle_;
};

template <typename T>
class Server
{
  public:
    void OnMessage(Message<T>& msg, std::shared_ptr<Connection<T>> remote)
    {
      std::cout << "OnMessage() from Server" << std::endl;
    }
};


int main()
{
  std::shared_ptr<Server<int>> server = std::make_shared<Server<int>>();
  std::shared_ptr<Connection<int>> connection = std::make_shared<Connection<int>>();
  connection->SetHandle(std::bind(&Server<int>::OnMessage, server, std::placeholders::_1, connection));
  connection->Run();
  return 0;
}

错误:

E:\Qt\Tools\mingw730_64\lib\gcc\x86_64-w64-mingw32.3.0\include\c++\bits\shared_ptr.h:661: error: no matching function for call to 'std::weak_ptr<int>::_M_assign(Connection<int>*&, const std::__shared_count<>&)'
In file included from E:/Qt/Tools/mingw730_64/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/memory:81:0,
                 from C:/Boost/include/boost-1_72/boost/asio/associated_allocator.hpp:19,
                 from C:/Boost/include/boost-1_72/boost/asio.hpp:20,
                 from D:\StudyDisk\Applications\QT\test_boost_connection\main.cpp:2:
E:/Qt/Tools/mingw730_64/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/bits/shared_ptr.h: In instantiation of 'void std::enable_shared_from_this<_Tp>::_M_weak_assign(_Tp1*, const std::__shared_count<>&) const [with _Tp1 = Connection<int>; _Tp = int]':
E:/Qt/Tools/mingw730_64/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/bits/shared_ptr_base.h:1373:6:   required from 'typename std::enable_if<std::__shared_ptr<_Tp, _Lp>::__has_esft_base<_Yp2>::value>::type std::__shared_ptr<_Tp, _Lp>::_M_enable_shared_from_this_with(_Yp*) [with _Yp = Connection<int>; _Yp2 = Connection<int>; _Tp = Connection<int>; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2; typename std::enable_if<std::__shared_ptr<_Tp, _Lp>::__has_esft_base<_Yp2>::value>::type = void]'
E:/Qt/Tools/mingw730_64/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/bits/shared_ptr_base.h:1301:35:   required from 'std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...) [with _Alloc = std::allocator<Connection<int> >; _Args = {}; _Tp = Connection<int>; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2]'
E:/Qt/Tools/mingw730_64/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/bits/shared_ptr.h:344:64:   required from 'std::shared_ptr<_Tp>::shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...) [with _Alloc = std::allocator<Connection<int> >; _Args = {}; _Tp = Connection<int>]'
E:/Qt/Tools/mingw730_64/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/bits/shared_ptr.h:690:14:   required from 'std::shared_ptr<_Tp> std::allocate_shared(const _Alloc&, _Args&& ...) [with _Tp = Connection<int>; _Alloc = std::allocator<Connection<int> >; _Args = {}]'
E:/Qt/Tools/mingw730_64/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/bits/shared_ptr.h:706:39:   required from 'std::shared_ptr<_Tp> std::make_shared(_Args&& ...) [with _Tp = Connection<int>; _Args = {}]'
D:\StudyDisk\Applications\QT\test_boost_connection\main.cpp:50:83:   required from here
E:/Qt/Tools/mingw730_64/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/bits/shared_ptr.h:661:4: error: no matching function for call to 'std::weak_ptr<int>::_M_assign(Connection<int>*&, const std::__shared_count<>&)'
  { _M_weak_this._M_assign(__p, __n); }
    ^~~~~~~~~~~~

我不明白。请帮忙!!!

std::enable_shared_from_this 要求您指定要启用的 class 的类型,并且正在派生。

您错误地指定了 T,而您启用的 class 是 Connection<T>

错误是(间接)指出隐藏的 weak_ptr 成员类型错误。

简而言之,这需要是您的 class 模板定义

template <typename T>
class Connection : public std::enable_shared_from_this<Connection<T>>
{
//...
};

您在滥用 std::enable_shared_from_this。它的模板参数需要是从它派生的类型,即 Connection<T>,但您传递的只是 T

所以,改变这个:

template <typename T>
class Connection : public std::enable_shared_from_this<T>

为此:

template <typename T>
class Connection : public std::enable_shared_from_this<Connection<T>>

然而,话虽如此,在此代码中根本没有理由使用 std::enable_shared_from_this,因为没有任何内容试图在 [=19] 上使用 shared_from_this()weak_from_this() =]对象。

此外,任何时候您想使用 std::bind(),请考虑改用 lambda。

试试这个:

#include <functional>
#include <iostream>
#include <memory>

template <typename T>
struct Message
{
    T a;
};

template <typename T>
class Connection
{
  typedef std::function<void(Message<T>&)> msg_handle;

  public:
    void SetHandle(msg_handle handle)
    {
      handle_ = handle;
    }

    void Run()
    {
      Message<T> t;
      std::cout << "Run() from Connection" << std::endl;
      handle_(t);
    }

  private:
    msg_handle handle_;
};

template <typename T>
class Server
{
  public:
    void OnMessage(Message<T>& msg, std::shared_ptr<Connection<T>> remote)
    {
      std::cout << "OnMessage() from Server" << std::endl;
    }
};


int main()
{
  auto server = std::make_shared<Server<int>>();
  auto connection = std::make_shared<Connection<int>>();
  connection->SetHandle([=](auto& m){ server->OnMessage(m, connection); });
  connection->Run();
  return 0;
}

Online Demo