智能指针作为使用 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;
}
#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;
}