Стандарт C ++: неожиданный const_iterator в мультимножестве - PullRequest
8 голосов
/ 10 января 2010

Недавно я столкнулся со странной проблемой, в которой я получал const_iterator вместо ожидаемого iterator при итерации по мультимножеству. Это оказалось не проблема для MSVC, но g ++ дал мне ошибку:

ошибка: неверная инициализация ссылка типа "myPtr &" из выражение типа 'const повышение :: shared_ptr '

Соответствующий код:

typedef std::multiset<myPtr> myList;
myList _mystuff;
void tick(float dt)
{
    for (myList::iterator i = _mystuff.begin(); i != _mystuff.end(); ++i)
    {
        myPtr &mine = *i; // g++ problem here, not for MSVC
        // const myPtr &mine = *i; works fine for g++
        mine->tick(dt);
    }
}

Немного исследований показали, что это проблема многих предыдущих обсуждений. Я нашел эти соответствующие биты:

Мои базовые знания и понимание этой проблемы ограничены, и поэтому я хотел бы знать, недостаточно ли стандарт определяет это поведение достаточно хорошо, и в этом случае g ++ и MSVC реализуют поведение по своему вкусу или g ++ или MSVC отклоняться от четко определенного стандарта.

Заранее спасибо.

Ответы [ 2 ]

16 голосов
/ 10 января 2010

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

Версия GCC, с которой вы тестируете, внесла это изменение, а версия VC, которую вы используете, - нет. VC10 (и VC9 SP1, я считаю) всегда возвращают const_iterators из наборов и мультимножеств.

23.2.4 / 6 последней версии C ++ 1x (на данный момент n3000.pdf):

Для ассоциативных контейнеров, где тип значения совпадает с ключом тип, итератор и const_iterator постоянные итераторы.

std :: set и std :: multi_set - это ассоциативные контейнеры, в которых тип значения совпадает с типом ключа.

1 голос
/ 12 февраля 2011

Как обмануть компилятор для std :: set :: iterator?

У меня есть структура

struct _item {
  int a;
  int b;
  bool operator <(const _item& x) const {return a<x.a;}
};

Я хочу изменить только элемент b (b не имеет значения для сортировки в наборе, сравнивается только элемент a).

std::set<_item> data;
std::set<_item>::iterator iter=data.begin();
iter->b=0;  // error !!!

Авада Кедавра!

struct _item {
  int a;
  int b;
  _item* self;
  _item() {self=this;} 
  bool operator <(const _item& x) const {return a<x.a;}
};
iter->self->b=0; // Success !! Tested on VC10

Конечно, больше C ++ правильно

struct _item {
  int a;
  int b;
 private:
  _item* self;
 public:
  _item() {self=this;} 
  bool operator <(const _item& x) const {return a<x.a;}
  int& bReference() const {return self->b;}
};
std::set<_item> items;
std::set<_item>::iterator iter=items.begin();
iter->bReference()=0; // Success !! Tested on VC1
...