以 class 作为键的地图,允许重复键
Map having a class as key, allows for duplicate keys
我有一个简单的地图程序。它以 class 作为键。 class 有多个成员。我假设我的比较函数是正确的。我遵循严格的弱排序。问题是,它允许输入重复的键。
下面是我的代码。
#include <iostream>
#include <string.h>
#include <map>
class mapkey
{
public:
std::string mInterface;
std::string mDestination;
int mPrefixLen;
std::string mNextHop;
int mMetric;
mapkey() {}
~mapkey() {}
mapkey(std::string a, std::string b, int c, std::string d, int e)
{
mInterface = a;
mDestination = b;
mPrefixLen = c;
mNextHop = d;
mMetric = e;
}
};
struct mapcomp
{
bool operator() (const mapkey left, const mapkey right);
};
bool mapcomp::operator() (const mapkey left, const mapkey right)
{
if(strcmp(left.mInterface.c_str(), right.mInterface.c_str()) < 0)
return true;
if(strcmp(left.mInterface.c_str(), right.mInterface.c_str()) > 0)
return false;
if(strcmp(left.mDestination.c_str(), right.mDestination.c_str()) < 0)
return true;
if(strcmp(left.mDestination.c_str(), right.mDestination.c_str()) > 0)
return false;
if(strcmp(left.mNextHop.c_str(), right.mNextHop.c_str()) < 0)
return true;
if(strcmp(left.mNextHop.c_str(), right.mNextHop.c_str()) > 0)
return false;
if(left.mPrefixLen < right.mPrefixLen)
return true;
if(left.mPrefixLen > right.mPrefixLen)
return false;
if(left.mMetric < right.mMetric)
return true;
if(left.mMetric > right.mMetric)
return false;
}
typedef std::map<mapkey, std::string, mapcomp> script_map;
script_map mm;
void print_map()
{
script_map::const_iterator iter;
for (iter = mm.begin(); iter != mm.end(); iter++)
{
std::cout << "value is - " << iter->second << std::endl;
}
}
int main()
{
mapkey test1("eth1", "50.60.70.80", 1, "90.10.20.30", 1);
mm[test1] = "first";
mapkey test2("eth1", "50.60.70.40", 1, "90.10.20.30", 1);
mm[test2] = "second";
mapkey test3("eth1", "50.60.70.20", 1, "90.10.20.30", 1);
mm[test3] = "third";
mapkey test4("eth1", "50.60.70.80", 1, "90.10.20.30", 1);
mm[test4] = "fourth";
print_map();
return 0;
}
以上程序,第一和第四键相同。当我打印地图时,输出如下
g++ --std=c++11 map.cpp
./a.out
值为 - 第三
值为 - 秒
值为 - 第 4
值为 - 第一个
我错过了什么?第四个条目应该没有被添加。
从这里开始:
if(strcmp(left.mInterface.c_str(), right.mInterface.c_str()) < 0)
return true;
if(strcmp(left.mInterface.c_str(), right.mInterface.c_str()) > 0)
return false;
strcmp()
returns 零且只有零,当字符串相等时。
然后看第一行:它 returns true
在所有其他成员有机会被比较之前。
原因:你的比较函数坏了。
解决方案:使用惯用的 C++ 编写一个新的。
struct mapcomp
{
bool operator() (mapkey const& l, mapkey const& r) {
return
std::tie(l.mInterface, l.mDestination, l.mPrefixLen, l.mNextHop, l.mMetric)
<
std::tie(r.mInterface, r.mDestination, r.mPrefixLen, r.mNextHop, r.mMetric)
;
}
};
- 我传递
mapkey const&
而不是 mapkey
以避免复制。
- 我使用元组比较和
std::tie
从您的成员中创建元组。
您还应该从 mapkey
中删除所有构造函数和析构函数。它们没有用处,因为您可以通过通用初始化来初始化成员。
我也会考虑为您的 class 将结构更改为 operator<
(也许 operator==
)的重载。 map
不通过任何其他比较器就可以接受它。
您的 mapcomp 方法并非在所有情况下都returning 一个值。您需要在函数末尾使用最终的 return false 来表示各项相等。
我建议使用内置的字符串 < 运算符并像这样重写您的 mapcomp 方法:
bool mapcomp::operator() (const mapkey& left, const mapkey& right)
{
if(left.mInterface < right.mInterface) return true;
if(left.mInterface > right.mInterface) return false;
if(left.mDestination < right.mDestination) return true;
if(left.mDestination > right.mDestination) return false;
if(left.mNextHop < right.mNextHop) return true;
if(left.mNextHop > right.mNextHop) return false;
if(left.mPrefixLen < right.mPrefixLen) return true;
if(left.mPrefixLen > right.mPrefixLen) return false;
if(left.mMetric < right.mMetric) return true;
if(left.mMetric > right.mMetric) return false;
return false; // items are equal
}
对于 C++,您可以使用
bool mapcomp::operator() (const mapkey left, const mapkey right)
{
if (left.mInterface != right.mInterface) return left.mInterface < right.mInterface;
if (left.mDestination != right.mDestination) return left.mDestination < right.mDestination;
if (left.mNextHop != right.mNextHop) return left.mNextHop < right.mNextHop;
if (left.mPrefixLen != right.mPrefixLen) return left.mPrefixLen < right.mPrefixLen;
if (left.mMetric != right.mMetric) return left.mMetric < right.mMetric;
return false; //equal != less
}
我有一个简单的地图程序。它以 class 作为键。 class 有多个成员。我假设我的比较函数是正确的。我遵循严格的弱排序。问题是,它允许输入重复的键。
下面是我的代码。
#include <iostream>
#include <string.h>
#include <map>
class mapkey
{
public:
std::string mInterface;
std::string mDestination;
int mPrefixLen;
std::string mNextHop;
int mMetric;
mapkey() {}
~mapkey() {}
mapkey(std::string a, std::string b, int c, std::string d, int e)
{
mInterface = a;
mDestination = b;
mPrefixLen = c;
mNextHop = d;
mMetric = e;
}
};
struct mapcomp
{
bool operator() (const mapkey left, const mapkey right);
};
bool mapcomp::operator() (const mapkey left, const mapkey right)
{
if(strcmp(left.mInterface.c_str(), right.mInterface.c_str()) < 0)
return true;
if(strcmp(left.mInterface.c_str(), right.mInterface.c_str()) > 0)
return false;
if(strcmp(left.mDestination.c_str(), right.mDestination.c_str()) < 0)
return true;
if(strcmp(left.mDestination.c_str(), right.mDestination.c_str()) > 0)
return false;
if(strcmp(left.mNextHop.c_str(), right.mNextHop.c_str()) < 0)
return true;
if(strcmp(left.mNextHop.c_str(), right.mNextHop.c_str()) > 0)
return false;
if(left.mPrefixLen < right.mPrefixLen)
return true;
if(left.mPrefixLen > right.mPrefixLen)
return false;
if(left.mMetric < right.mMetric)
return true;
if(left.mMetric > right.mMetric)
return false;
}
typedef std::map<mapkey, std::string, mapcomp> script_map;
script_map mm;
void print_map()
{
script_map::const_iterator iter;
for (iter = mm.begin(); iter != mm.end(); iter++)
{
std::cout << "value is - " << iter->second << std::endl;
}
}
int main()
{
mapkey test1("eth1", "50.60.70.80", 1, "90.10.20.30", 1);
mm[test1] = "first";
mapkey test2("eth1", "50.60.70.40", 1, "90.10.20.30", 1);
mm[test2] = "second";
mapkey test3("eth1", "50.60.70.20", 1, "90.10.20.30", 1);
mm[test3] = "third";
mapkey test4("eth1", "50.60.70.80", 1, "90.10.20.30", 1);
mm[test4] = "fourth";
print_map();
return 0;
}
以上程序,第一和第四键相同。当我打印地图时,输出如下
g++ --std=c++11 map.cpp
./a.out
值为 - 第三
值为 - 秒
值为 - 第 4
值为 - 第一个
我错过了什么?第四个条目应该没有被添加。
从这里开始:
if(strcmp(left.mInterface.c_str(), right.mInterface.c_str()) < 0)
return true;
if(strcmp(left.mInterface.c_str(), right.mInterface.c_str()) > 0)
return false;
strcmp()
returns 零且只有零,当字符串相等时。
然后看第一行:它 returns true
在所有其他成员有机会被比较之前。
原因:你的比较函数坏了。
解决方案:使用惯用的 C++ 编写一个新的。
struct mapcomp
{
bool operator() (mapkey const& l, mapkey const& r) {
return
std::tie(l.mInterface, l.mDestination, l.mPrefixLen, l.mNextHop, l.mMetric)
<
std::tie(r.mInterface, r.mDestination, r.mPrefixLen, r.mNextHop, r.mMetric)
;
}
};
- 我传递
mapkey const&
而不是mapkey
以避免复制。 - 我使用元组比较和
std::tie
从您的成员中创建元组。
您还应该从 mapkey
中删除所有构造函数和析构函数。它们没有用处,因为您可以通过通用初始化来初始化成员。
我也会考虑为您的 class 将结构更改为 operator<
(也许 operator==
)的重载。 map
不通过任何其他比较器就可以接受它。
您的 mapcomp 方法并非在所有情况下都returning 一个值。您需要在函数末尾使用最终的 return false 来表示各项相等。
我建议使用内置的字符串 < 运算符并像这样重写您的 mapcomp 方法:
bool mapcomp::operator() (const mapkey& left, const mapkey& right)
{
if(left.mInterface < right.mInterface) return true;
if(left.mInterface > right.mInterface) return false;
if(left.mDestination < right.mDestination) return true;
if(left.mDestination > right.mDestination) return false;
if(left.mNextHop < right.mNextHop) return true;
if(left.mNextHop > right.mNextHop) return false;
if(left.mPrefixLen < right.mPrefixLen) return true;
if(left.mPrefixLen > right.mPrefixLen) return false;
if(left.mMetric < right.mMetric) return true;
if(left.mMetric > right.mMetric) return false;
return false; // items are equal
}
对于 C++,您可以使用
bool mapcomp::operator() (const mapkey left, const mapkey right)
{
if (left.mInterface != right.mInterface) return left.mInterface < right.mInterface;
if (left.mDestination != right.mDestination) return left.mDestination < right.mDestination;
if (left.mNextHop != right.mNextHop) return left.mNextHop < right.mNextHop;
if (left.mPrefixLen != right.mPrefixLen) return left.mPrefixLen < right.mPrefixLen;
if (left.mMetric != right.mMetric) return left.mMetric < right.mMetric;
return false; //equal != less
}