2016-10-18 2 views
0

следующая структура:Как установить работу вставки в следующей ситуации?

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 вставить путем замены. Можно ли использовать этот метод в моем коде? или это вызовет проблемы в будущем (даже если я его зарегистрирую)?

+1

Вы прочитали дружественное руководство? –

+1

Если вы хотите, чтобы они вставляли их оба, измените свои функции сравнения, чтобы они проверяли как «значение», так и «данные». В противном случае это игнорируется. – Barmar

+0

Фактически, предполагается, что он зависит только от 'value'. Мой код требует замены существующего элемента на новый. Но является ли поведенческая часть стандарта? Или это изменится с помощью компилятора? –

ответ

1

От documentation:

проверки работы вставки ли каждый вставлен элемент эквивалентен элементу уже в контейнере, и если да, то элемент не вставлен

Так TheSet.insert(st2); будет не вставляйте ничего, потому что st2 равен st1, который уже в комплекте.

Если вы хотите, чтобы иметь возможность вставить оба, вы должны изменить функции сравнения, так они испытывают как value и data, или использовать std::multiset, что позволяет повторяющиеся записи.

+0

Спасибо. Фактически, я сознательно делал это зависящим только от «ценности». Я также хочу, чтобы он заменил 'st1', когда вставлен' st2'. Теперь я думаю, что структура данных opt для этой задачи - 'std :: map', а не' std :: set'. –

Смежные вопросы