以下结构:
struct SomeStructure {
uint64_t value;
uint64_t data;
};
bool operator > (const SomeStructure& v1, const SomeStructure& v2) {
return (v1.value > v2.value);
}
bool operator < (const SomeStructure& v1, const SomeStructure& v2) {
return (v1.value < v2.value);
}
bool operator == (const SomeStructure& v1, const SomeStructure& v2) {
return (v1.value == v2.value);
}
用于类似以下的代码:
SomeStructure st1, st2;
st1.value = st2.value = 10; // has the same 'value'
st1.data = 20; // but is assigned a different number for the 'data'.
st2.data = 40;
std::set<SomeStructure> TheSet;
TheSet.insert(st1);
TheSet.insert(st2);
在st2
之后插入st1
会替换集合中存在的元素的值吗?
在上面的示例中,由于运算符>
和<
重载仅依赖于成员SomeStructure::value
,因此st2
和st1
都被视为在将它们插入TheSet
时保持平等。但是SomeStructure::data
的值对于这两个对象都是不同的。那么它会替换TheSet
中的现有元素,还是如果元素已经存在则会忽略插入操作?
有没有办法明确执行这两种行为?
此行为会随编译器和平台而改变吗?
修改1:
我刚用g ++编译器测试了这个(启用了c ++ 11)。它不会取代。那么有没有办法明确强制执行此操作来替换现有元素?
编辑2:
实际上,没有标准的方法来强制执行&#34;这种行为,但可以使用简单的 hack through 来完成。虽然不建议使用此方法,但请在此处介绍:
必须使用此方法代替std :: set
中的成员函数插入template <typename T>
void insert_replace(std::set <T>& theSet, const T& toInsert) {
auto it = theSet.find(toInsert);
if(it != theSet.end())
*((T*)&(*it)) = toInsert;
else
theSet.insert(toInsert);
}
以上代码必须替换为:
int main() {
SomeStructure st1, st2;
st1.value = st2.value = 10; // has the same 'value'
st1.data = 20; // but is assigned a different number for the 'data'.
st2.data = 40;
std::set<SomeStructure> TheSet;
insert_replace (TheSet, st1);
insert_replace (TheSet, st2);
for(auto ii : TheSet) {
std::cout << ii.data;
}
return (0);
}
此方法适用于我的编译器,提供输出:40
,而不是20
。但我认为人们可能会说这不是推荐的方法,因为行*((T*)&(*it)) = toInsert;
使编译器误以为迭代器it
不是常数(但实际上是)。我相信这是我们通过替换强制插入std::set
的唯一方法。在我的代码中使用此方法是否可以?或者它会在将来引起问题(即使我记录了它)?
答案 0 :(得分:1)
插入操作检查每个插入的元素是否等同于容器中已有的元素,如果是,则不插入元素
所以TheSet.insert(st2);
不会插入任何内容,因为st2
等于st1
,它已经在集合中。
如果您希望能够同时插入它们,则需要更改比较函数,以便它们同时测试value
和data
,或使用std::multiset
,这允许重复输入