2017-02-06 13 views
0

я должен реорганизовать старый код, который выглядит следующим образом (я не очень опытный C++ кодер)Лучший способ заменить множество в C++

std::set<SomeObject>::iterator it = setobject.begin(); 

do { 
    it->setProperty1ToNextValue(); 
    it->getProperty2(); 
    it->getProperty3(); 
    it++ 
} while (it != setobject.end()); 

В основном я хочу перебирать элементы множества и получить и установить/обновить некоторые из своих свойств. я не могу использовать оригинальный набор, так как я бегу проблем, описанных в этой теме the object has type qualifiers that are not compatible with the member function object type is const

Я имею в виду заменить набор с DEQUEUE (он будет включать некоторые переписывания), так как я тогда будет в состоянии установить и получить свойства на каждом элементе dequeue. Это хороший подход?

+0

Если политики 'std :: set' больше не применяются, что вам на самом деле нужно? Может быть, 'std :: unordered_map'? Кстати, все ваши вызовы функций в образце кажутся NOP, если нет каких-либо побочных эффектов. Рассмотрите размещение _real code_. –

+1

Почему, по-вашему, вы не можете использовать set? – koalo

+2

Вы не можете изменить ключевые свойства набора, но вы можете удалить элемент со старыми свойствами и заменить его на новый. Сказав это, если вы выполняете итерацию через набор, у вас, вероятно, есть неправильная структура данных. –

ответ

3

A std::set работает, держа все предметы в порядке в соответствии с оператором < объекта. Причина, по которой вы не можете вызывать неконстантные методы для вашего объекта, состоит в том, что существует риск того, что эти методы изменят значение, возвращаемое вашим оператором <, и, следовательно, эффективно «переупорядочить» набор под капотом без знания std::set.

Хотя вы не указали достаточно того, что вы пытаетесь сделать для нас, чтобы предоставить лучший ответ, вот несколько способов технически добиться вызова некоторых методов на вашем наборе. Вы можете использовать const_cast для вызова методов, которые, как вы уверены, не будут изменять ключ. Или вы можете поместить элементы в вектор, вызвать методы, которые могут изменить «ключ», а затем вернуть их обратно в исходный набор.

// Example program 
#include <iostream> 
#include <string> 
#include <set> 
#include <algorithm> 

class SomeObject 
{ 
    std::string key; 
    int   data; 

public: 
    SomeObject(const std::string& key_, int data_) : key(key_), data(data_) 
    {} 

    // For a item to be in a set, it must have a "<" operator that tells it how to order it 
    bool operator <(const SomeObject& rhs) const 
    { 
     return key < rhs.key; 
    } 

    void setKey(const std::string& key_) 
    { 
     key = key_; 
    } 

    void setData(int data_) 
    { 
     data = data_; 
    } 
}; 

int main() 
{ 
    std::set<SomeObject> setobject; 
    setobject.insert(SomeObject("c", 1)); 
    setobject.insert(SomeObject("a", 1)); 
    setobject.insert(SomeObject("b", 1)); 

    // internally, the set will keep everything in order "a", "b", "c" 

    // option 1 - use const_cast (risky!) 
    { 
     std::set<SomeObject>::iterator it = setobject.begin(); 

     do { 
      // const_cast< SomeObject& >(*it).setKey("d"); bad idea, now the set is jacked up because its not in the right order 
      const_cast< SomeObject& >(*it).setData(2); 
      it++; 
     } while (it != setobject.end()); 
    } 

    // option 2 - put the items in the vector, call the methods, then put them back in the original set 
    { 
     std::vector<SomeObject> tempVec(std::begin(setobject), std::end(setobject)); 
     std::vector<SomeObject>::iterator it = tempVec.begin(); 
     do { 
      it->setKey("d"); 
      it->setData(2); 
      it++; 
     } while (it != tempVec.end()); 

     std::set<SomeObject> newSet(std::begin(tempVec), std::end(tempVec)); 
     std::swap(newSet, setobject); // put the new items back in the original setobject 
    } 



} 

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

  • Нет связанных вопросов^_^