【问题标题】:Placing boost socket into std::map将 boost socket 放入 std::map
【发布时间】:2019-10-31 05:51:12
【问题描述】:

我在想这会很直接,但我一定错过了一些关键的东西,因此错误 =O。 我在源文件中收到“使用已删除函数”错误。

无论如何,我知道我的头文件已正确连接,因为它已在整个源文件中正确调用,除了这一行之外,源代码 sn-p 是唯一需要评估的地方。

标头源代码

using boost::asio::ip::tcp;
tcp::acceptor mAcceptor;
std::map<std::string, tcp::socket> mSockets;

源文件代码

tcp::socket socket(ioService);
mAcceptor.accept(socket);
std::string myKey = "Socket"; // Didn't add actual key string creation
mSockets[myKey] = socket;

错误

错误:使用删除函数'boost::asio::basic_stream_socket& boost::asio::basic_stream_socket::operator{const boost::asio::basic_stream_socket&)' mSockets[myKey] = 套接字;

接着说: 隐式声明为已删除,因为 'boost::asio::basic_stream_socket' 声明了移动构造函数或移动赋值运算符类 basic_stream_socket。

更新

@Radosław Cybulski 建议尝试 std::move(socket) ,这消除了很大一部分错误,但现在导致了。

错误 #2

'boost::asio::basic_stream_socket::basic_stream_socket()' 秒(std::forward<_args2>(std::get<_indexes2>(_tuple2))...)

【问题讨论】:

  • 不要在已回答的问题中添加更多问题。创建一个新问题。
  • 这很奇怪。我无法想象单个对象直接管理多个套接字的代码。在我的代码中,单个套接字由处理套接字逻辑的某个类包装,并且只有该对象由其他东西聚合。

标签: c++ c++11 boost


【解决方案1】:

试试:

mSockets.insert({ myKey, std::move(socket) });

复制操作符被删除,因为没有复制socket的好方法。我的意思是,你连接到某个东西,然后复制,现在呢?您可以同时发送两份副本,只发送一份(哪一份?),其他的?所以它被删除了,如果你想传递它,请使用移动构造函数/赋值和std::move

编辑:由于空的构造函数也被删除,你不能使用mSockets[key] = ...。所以我们必须依赖insert / emplace。为什么?地图上的operator[] 需要存在值类型的默认构造函数。我不知道为什么,但就是这样。

【讨论】:

  • 这解决了一半的问题,最新的错误说“没有匹配函数调用'boost::asio::basic_stream_socket<:asio::ip::tcp>::basic_stream_socket() ' second(std::forward<_args2>(std::get<_indexes2>(_tuple2))...)。谢谢你的建议,可能只是少了一个组件。
  • @KyleJ 如果您的问题已得到解答,请接受答案。
  • @TedLyngmo 没有。
  • 给我一秒钟。固定。
  • 这里的问题是operator[],它默认插入一个带有默认构造函数的值。由于boost::asio::ip::tcp::socket 没有,所以有问题。
【解决方案2】:

您不能将mapboost::asio::ip::tcp::socket 一起用作值,因为map 要求其值是默认可构造的(例如,在调用map::operator[] 时会创建默认构造实例),asio::ip::tcp::socket 不满足这是因为它的 ctor 至少需要将 io_context 对象作为参数。

使用shared_ptrunique_ptr 作为映射的值。

【讨论】:

  • 这是有道理的。我见过有人使用带有 shared_ptr 的向量。感谢您的再次确认!
  • 不是std::map 要求包含的值类型是默认可构造的。它是operator[]( const Key&amp; key );,所以emplaceoperator[]( Key&amp;&amp; key ) 适用于没有默认构造函数的类型。
  • @TedLyngmo operator[] 移动语义不起作用 - demo on godbolt。但总的来说你是对的,只有operator[] 要求映射值是默认可构造的,而不是map 的所有成员。也许我过于概括了我的答案,但是当我使用某个容器时,我希望它的所有成员都启用,而不是像emplace 这样的技巧来插入新值。
  • @rafix07 你说得对,它不适用于默认分配器,我还没有尝试自己制作。看起来很吓人 :-) 但是,emplace 对我来说似乎还不错。
  • 一种解决方法是首先检查映射中是否存在密钥,如果不存在,则将所需的那个推入。没有默认构造函数。它对我有用,至少在我遇到的类似问题上。
【解决方案3】:

套接字不能是默认构造的,并且您使用的运算符要求它就是这样(使用默认分配器时)。

T& std::map::operator[](const Key& key):

[...] value_type 必须是来自
std::piecewise_construct, std::forward_as_tuple(key), std::tuple&lt;&gt;()EmplaceConstructible。当使用默认分配器时,这意味着 key_type 必须是 CopyConstructible mapped_type 必须是 DefaultConstructible

但是,您可以使用 emplace() 并将套接字移动到正在构建的 std::pair&lt;std::string, tcp::socket&gt; 中:

auto [it, inserted] = mSockets.emplace(myKey, std::move(socket));

这将使用tcp::socket(tcp::socket&amp;&amp;) 构造函数move-construct 套接字而不是tcp::socket()(您已经注意到它不存在)。

【讨论】:

    猜你喜欢
    • 2012-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-03
    • 2017-07-15
    • 2019-08-19
    相关资源
    最近更新 更多