Есть ли std :: map:: итератор создает экземпляр std :: map? - PullRequest
15 голосов
/ 08 марта 2019

У меня есть этот код, который работает на GCC:

#include <map>

class Foo;
class Bar;

typedef std::map<Foo,Bar> MyMap;

MyMap::iterator i;

class Foo
{
    MyMap::iterator some_data;
};

Код, разработанный в настоящее время (неприятно округлый, да, я застрял с ним) требует, чтобы map<Foo,Bar>::iterator был доступен для Foo и Bar.

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

Это гарантировано? Стандарт, кажется, несколько непривычен, когда дело доходит до определения типа итератора карты. Насколько переносим этот код?

Ответы [ 2 ]

3 голосов
/ 09 марта 2019

Это приводит к неопределенному поведению.

В объявлении MyMap::iterator i; требуется, чтобы MyMap был полным типом, поэтому он создается неявно. Тем не менее, Foo и Bar не являются полными на данном этапе создания экземпляра, поэтому поведение не определено в соответствии с [res.on.functions] / 2 :

В частности, эффекты не определены в следующих случаях:

  • ...
  • если неполный тип ([basic.types]) используется в качестве аргумента шаблона при создании экземпляра компонента шаблона или оценке концепции, если это специально не разрешено для этого компонента.
0 голосов
/ 08 марта 2019

Можно обойти весь вопрос, учитывая тот факт, что std::map является контейнером на основе узлов, поэтому его узлы, содержащие элементы, имеют стабильные адреса. То есть вы можете использовать простой указатель вместо итератора (если, конечно, вам не нужен итератор для передачи в функции-члены std::map):

class Foo
{
    std::pair<Foo const, Bar>* some_data;
};

Обратите внимание, что для определения члена some_data.

необходимы только объявления для Foo, Bar и std::pair<>.

Если вы используете boost::multi_index (который во многих отношениях превосходит std ассоциативные контейнеры), то он имеет чрезвычайно полезные функции to_iterator, которые принимают ссылку на элемент и возвращают итератор.

...