是否有一个std::map
的密钥,该密钥考虑了密钥的滚动或换行?如果是这样,您将如何实现<运算符来做到这一点?
假设键是基于一个最大值为N的计数器,则可以有一个<运算符,该运算符会在键值翻转时加以考虑,以便在地图中按以下顺序对各项进行排序:< / p>
N-2
N-1
N
1
2
3
...
此外,如果可以跳过键值,是否可以这样做?例如,跳过N以便地图具有以下值:
N-2
N-1
1
2
3
...
答案 0 :(得分:0)
答案 1 :(得分:0)
这里是如何实现此示例。这个想法是要引入一个自定义Key
模板,该模板可以在编译时用所需的最大值进行参数设置。通过boost operator library提供比较和基本算术运算,以使Key
实例具有相同的最大值。值可以进行比较和添加。
#include <boost/operators.hpp>
template <int max>
struct Key : private boost::totally_ordered<Key<max>, boost::addable<Key<max>>> {
int value;
Key(int init = 0) : value(init) { maybeRollOver(); }
Key& operator+=(const Key& rhs) { value += rhs.value; maybeRollOver(); return *this; }
const Key& operator+() const { return *this; }
void maybeRollOver() { if (value > max) value = value % max - 1; }
};
此模板需要两个运算符重载才能生成所有比较运算符(请参见boost docs):
template <int max>
bool operator==(const Key<max>& lhs, const Key<max>& rhs)
{
return lhs.value == rhs.value;
}
template <int max>
bool operator<(const Key<max>& lhs, const Key<max>& rhs)
{
return lhs.value < rhs.value;
}
这是使用方法。
std::map<Key<5>, std::string> testMap;
testMap[0] = "Hello";
testMap[1] = "world";
testMap[6] = "Bye"; // "rolled over to 0, "Hello" is replaced by "Bye";
for (const auto& [key, value] : testMap)
std::cout << key.value << ": " << value << "\n";
答案 2 :(得分:0)
这是我能够上班的解决方案。
密钥实际上是<unsigned int, unsigned int>
,相对于翻转的顺序只需要考虑密钥的第一个值。
另外,该ID基于1,因此值将为1, 2, ..., N, 1, 2, ...
最后,请注意,MAX ID足够大,因此我们永远不会有多个相同的键试图同时存在于映射中。也就是说,当我们到达ID N时,最初的1、2、3 ...键早已消失。
class Mykey(
public:
unsigned int Id1;
unsigned int Id2;
MyKey(unsigned int k1, unsigned in k2)
: Id1(k1), Id2(k2) {}
bool operator<(const MyKey &rhs) const
{
if (Id1 == rhs.Id1)
return Id2 < rhs.Id2;
else if ( (rhs.Id1 > Id1) && (rhs.Id1 - Id1 > MAX_ID/2) )
return false;
else if ( (Id1 > rhs.Id1) && (Id1 - rhs.Id1 > MAX_ID/2) )
return true;
else
return Id1 < rhs.Id1;
}
假设MAX_ID为25,则第一个否则考虑rhs.Id1为25而Id1为1的情况。第二个其他情况考虑Id1 = 25而rhs.Id1 = 1的相反情况。 MAX_ID / 2正在检查两个值是否“相距较远”,以表示ID换行。