2017-02-06 2 views
0

Je dois factoriser ancien code qui ressemble à ceci (je ne suis pas très compétent codeur ++ C)La meilleure façon de remplacer un ensemble en C++

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

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

Fondamentalement, je veux itérer les éléments de l'ensemble et obtenir et définir/mettre à jour certaines de leurs propriétés. Je ne peux pas utiliser le jeu d'origine depuis que je cours dans les problèmes décrits dans ce fil the object has type qualifiers that are not compatible with the member function object type is const

Je pense à remplacer l'ensemble avec un dequeue (il implique une ré-écriture) car je serai alors en mesure de définir et obtenir propriétés sur chaque élément de la file d'attente. Est-ce une bonne approche?

+0

Si les stratégies 'std :: set' ne s'appliquent plus, de quoi avez-vous réellement besoin? Un 'std :: unordered_map' peut-être? BTW, tous vos appels de fonction dans l'échantillon semblent être des NOP, sauf s'il y a des effets secondaires. Pensez à poster _real code_. –

+1

Pourquoi pensez-vous que vous ne pouvez pas utiliser set? – koalo

+2

Vous ne pouvez pas modifier les propriétés de clé d'un ensemble, mais vous pouvez supprimer l'élément avec les anciennes propriétés et le remplacer par un nouveau. Cela dit, si vous itérez à travers un ensemble, vous avez probablement la mauvaise structure de données. –

Répondre

3

Un std::set fonctionne en conservant tous les éléments dans l'ordre en fonction de l'opérateur < de l'objet. La raison pour laquelle vous ne pouvez pas appeler des méthodes non-const sur votre objet est qu'il existe un risque que ces méthodes modifient la valeur renvoyée par votre opérateur <, et donc réorganisent effectivement l'ensemble sous le capot sans connaître le std::set.

Bien que vous n'ayez pas suffisamment spécifié ce que vous essayez de faire pour nous fournir la meilleure réponse, voici quelques façons d'obtenir techniquement l'appel de certaines méthodes sur votre poste. Vous pouvez utiliser const_cast pour appeler des méthodes dont vous êtes sûr de ne pas modifier la clé. Vous pouvez également placer les éléments dans un vecteur, appeler des méthodes susceptibles de modifier la "clé", puis les remettre dans l'ensemble d'origine.

// 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 
    } 



}