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
}
}
Если политики 'std :: set' больше не применяются, что вам на самом деле нужно? Может быть, 'std :: unordered_map'? Кстати, все ваши вызовы функций в образце кажутся NOP, если нет каких-либо побочных эффектов. Рассмотрите размещение _real code_. –
Почему, по-вашему, вы не можете использовать set? – koalo
Вы не можете изменить ключевые свойства набора, но вы можете удалить элемент со старыми свойствами и заменить его на новый. Сказав это, если вы выполняете итерацию через набор, у вас, вероятно, есть неправильная структура данных. –