【问题标题】:Unable to add multiple keys to map having struct as key无法将多个键添加到以结构为键的映射
【发布时间】:2018-10-25 09:23:20
【问题描述】:

我正在尝试将多个键值对添加到 map having struct as both its key and value。由于某些原因,只有我添加的第一个键值对被添加到地图中,并且找不到第二个键值对。

#include<string>
#include<iostream>
#include<map>
using namespace std;

struct RJNodeAddress
{
            string m_ip;
            string m_port;
            bool operator<(const RJNodeAddress &l)const
            {
                    int l_size=l.m_ip.size();
                    int r_size=l.m_port.size();                                          
                    return (l_size < r_size);
            }
};

struct RJNodeDetails
{
        string m_NodeType;
        int        m_appId;
};

class RJWebsocket
{
        public:
            static map<RJNodeAddress,RJNodeDetails> m_Nodes;
};

map<RJNodeAddress,RJNodeDetails> RJWebsocket::m_Nodes;

int main()
{
        RJNodeAddress l_node1,l_node2;
        RJNodeDetails l_add1,l_add2;

        l_node1.m_ip="172.16.129.68";
        l_node1.m_port="8766";
        l_node2.m_ip="172.16.128.130";
        l_node2.m_port="8768";

        l_add1.m_appId=0;
        l_add1.m_NodeType="CM";

        l_add1.m_appId=1;
        l_add1.m_NodeType="CM";

        RJWebsocket::m_Nodes.insert({l_node1,l_add1});
        RJWebsocket::m_Nodes.insert({l_node2,l_add2});

    for(const auto& j:RJWebsocket::m_Nodes)
    {
    cout<<endl<<"Iterating through RJWebsocket::m_Nodes"<<endl;
    cout<<endl<<"port: "<<j.first.m_port<<"  "<<"IP: "<<j.first.m_ip<<endl;
    }

}

上面的代码给出以下输出:

Iterating through RJWebsocket::m_Nodes

port: 8766  IP: 172.16.129.68

【问题讨论】:

标签: c++ std


【解决方案1】:

您的比较运算符做了一些奇怪的事情,我建议依靠std::tuple 提供的比较运算符,如下所示:

#include <tuple>

bool operator<(const RJNodeAddress &l)const
{
    return std::tie(m_ip, m_port) < std::tie(l.m_ip, l.m_port);
}

这样,std::map::insert 中的等价性检查可以正确执行,并且 main 函数中的 sn-p 确实构造了两个条目。然后我机器上的输出是

Iterating through RJWebsocket::m_Nodes

port: 8768  IP: 172.16.128.130

Iterating through RJWebsocket::m_Nodes

port: 8766  IP: 172.16.129.68

请注意,正如 @DanielLangr 在 cmets 中指出的那样,RJNodeAddress 也可以直接是 std::pair&lt;std::string, std::string&gt;std::tuple&lt;std::string, std::string&gt; 的类型别名,它提供了开箱即用的字典式 operator &lt; 并回退到 @987654329 @。这使您不必手动指定比较,但有两个缺点:它不提供命名 struct 及其数据成员的表达能力,而且它的字典比较可能不是您最初想要的。

【讨论】:

  • 或者,将RJNodeAddress 本身定义为一个元组/字符串对。
  • @DanielLangr 对,这是一个非常相似的解决方案。感谢您的建议,我会在答案中添加提示。
  • 这只是一个评论,因为我们实际上并不知道 OP 如何比较 RJNodeAddress 的实例。
【解决方案2】:

您的运营商不尊重compare requirement

bool operator<(const RJNodeAddress &l)const
{
        int l_size=l.m_ip.size();
        int r_size=l.m_port.size();                                          
        return (l_size < r_size); // Wrong
}

你可能想要这样的东西:

bool operator<(const RJNodeAddress &rhs)const
{
    auto as_tuple = [](const RJNodeAddress & a){std::tie(a.m_ip, a.m_port); };
    return as_tuple(*this) < as_tuple(rhs);
}

【讨论】:

    【解决方案3】:

    您的operator&lt; 应该在两个不同的RJNodeAddress 之间进行比较,您似乎只看操作数(l)。试试这样的:

            bool operator<(const RJNodeAddress &l)const
            {
                if (m_ip == l.m_ip)
                    return m_port < l.m_port;
                return m_ip < l.m_ip;
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-07
      • 1970-01-01
      • 1970-01-01
      • 2019-01-18
      • 2011-04-06
      相关资源
      最近更新 更多