следующая структура:Как установить работу вставки в следующей ситуации?
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
или проигнорирует операцию вставки, если элемент уже присутствует?
Есть ли способ явно навязать любое из этих двух способов поведения?
Будет ли это изменяться с помощью компилятора и платформы?
Edit 1:
Я только проверил это в г ++ компилятор (с C++ 11 включен). Он не заменяет. Итак, есть ли способ принудительно выполнить это, чтобы заменить существующий элемент?
Edit 2:
На самом деле, нет никакого стандартного способа «применять» такое поведение, но это может быть сделано с помощью простой взломать через. Хотя этот метод не рекомендуется, позвольте мне представить его здесь:
Этот метод должен быть использован вместо функции члена вставки в станд :: установить
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
вставить путем замены. Можно ли использовать этот метод в моем коде? или это вызовет проблемы в будущем (даже если я его зарегистрирую)?
Вы прочитали дружественное руководство? –
Если вы хотите, чтобы они вставляли их оба, измените свои функции сравнения, чтобы они проверяли как «значение», так и «данные». В противном случае это игнорируется. – Barmar
Фактически, предполагается, что он зависит только от 'value'. Мой код требует замены существующего элемента на новый. Но является ли поведенческая часть стандарта? Или это изменится с помощью компилятора? –