Можно ли заставить STL установить переоценку предиката? - PullRequest
0 голосов
/ 20 ноября 2018

Рассмотрим следующие структуры данных и код.

struct Sentence {
    std::string words;
    int frequency;
    Sentence(std::string words, int frequency) : words(words), frequency(frequency) {}
};
struct SentencePCompare {
    bool operator() (const Sentence* lhs, const Sentence* rhs) const {
        if (lhs->frequency != rhs->frequency) {
            return lhs->frequency > rhs->frequency;
        }
        return lhs->words.compare(rhs->words) < 0;
    }
};
std::set<Sentence*, SentencePCompare> sentencesByFrequency;

int main(){
    Sentence* foo = new Sentence("foo", 1);
    Sentence* bar = new Sentence("bar", 2);
    sentencesByFrequency.insert(foo);
    sentencesByFrequency.insert(bar);
    for (Sentence* sp : sentencesByFrequency) {
        std::cout << sp->words << std::endl;
    }
    foo->frequency = 5;
    for (Sentence* sp : sentencesByFrequency) {
        std::cout << sp->words << std::endl;
    }
}

Вывод приведенного выше кода выглядит следующим образом.

bar
foo
bar
foo

Как и следовало ожидать, когда объект указывает науказатель в наборе обновляется, набор не переоценивает предикат автоматически, даже если предикат упорядочивает указатели на основе объектов, на которые они указывают.

Есть ли способ принудительно вызватьstd::set переоценить предикаты, чтобы снова был правильный порядок?

1 Ответ

0 голосов
/ 20 ноября 2018

Нет.

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

ПередВ C ++ 17 вам нужно снова набрать erase и insert, что влечет за собой копирование ключа плюс освобождение и выделение узла.После этого вы можете extract узел, изменить его и заново установить, что бесплатно.

...