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
}
}
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_. –
Pourquoi pensez-vous que vous ne pouvez pas utiliser set? – koalo
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. –