STL-итераторы и const - PullRequest
       34

STL-итераторы и const

4 голосов
/ 28 июля 2010

У меня проблема с тем, что кажется неким неявным приведением к const, когда я использую итераторы.Я не совсем уверен, какой код важен (если бы я это сделал, я бы не стал задавать этот вопрос!), Поэтому я постараюсь показать свою проблему как можно лучше.

typedef set<SmallObject> Container;              //not const

void LargeObject::someFunction() {               //not const
    Container::iterator it;                      //not const
    for (it = c.begin(); it != c.end(); ++it) {  //assume c is a "Container"
        (*it).smallObjectFunction();             //not a const function
    }
}

Однако я всегда получаюследующая ошибка:

error: passing 'const SmallObject' as 'this' argument of 'int SmallObject::smallObjectFunction()' discards qualifiers

Однако, если я приведу его как ((SmallObject)(*it).smallObjectFunction();, я избавлюсь от сообщения об ошибке.

Единственное, что я могу понять, это то, что каким-то образом определение

bool operator< (const SmallObject &a) const;

так или иначе заставляет итератор возвращать константные объекты.Любая помощь или объяснение здесь?

Ответы [ 3 ]

11 голосов
/ 28 июля 2010

Наборы и карты сохраняют элементы в порядке согласно условию сортировки. Чтобы код пользователя не нарушал инварианты, key карты и весь элемент в наборе должны быть постоянными. Ваша проблема в том, что хранимый элемент не SmallObject, а const SmallObject.

Если бы это не было ограничено, вы могли бы иметь:

int init[] = { 1, 2, 3, 4, 5 };
std::set<int> values( init, init+5 );
std::copy( values.begin(), values.end(), 
   std::ostream_iterator<int>(std::cout, " "));
   // 1 2 3 4 5
*(values.find(3)) = 5; // luckily this does not work!
std::copy( values.begin(), values.end(), 
   std::ostream_iterator<int>(std::cout, " "));
   // 1 2 5 4 5 -- not in order!!!

Проблема не только в том, что теперь элемент набора будет не в порядке, но и в том, что в зависимости от того, как было построено дерево, могут быть элементы, которые присутствуют в наборе, но не могут быть найдены.

3 голосов
/ 19 декабря 2010

Ваш код не глуп и может скомпилироваться без ошибок с соответствующей реализацией STL, в зависимости от некоторых проектных решений, принятых вашей реализацией STL. Стандарт C ++ 03 не определяет, какой должна быть ссылка typedef для set :: iterators (по моему мнению, они должны быть непостоянными ссылками). Так что продолжайте делать то, что вы делаете, но вставьте const_cast :

const_cast<SmallObject&>(*it).smallObjectFunction();

Это более эффективно и намного понятнее, чем стирание и повторная вставка. Для более подробного обсуждения этой проблемы, ознакомьтесь с пунктом 8 в «Более исключительном C ++» Херба Саттера.

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

0 голосов
/ 28 июля 2010

Объект (ы) в вашем контейнере c являются константными, а функция smallObjectFunction пытается изменить значение объекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...