Каковы правила для стандартных библиотечных контейнеров и неполных типов?

Учитывая неполный тип:

struct S; 

Тогда следующие объявления:

S *p;            // ok, pointer to incomplete types is allowed

std::deque<S> l;  // error, instantiating std::deque with incomplete type is UB

Но как насчет следующих объявлений?

std::deque<S> *p;   // seems to be UB like the previous case, 
                   // but is it ok if p is not used till S is defined?

std::deque<S*> p;   // not really sure about this one

Изменить: в вопросе использовалось std::list вместо std::deque, но это противоречит цели вопроса, поскольку std::list явно разрешено использовать неполные типы. std::deque не имеет такого разрешения.


person cigien    schedule 23.07.2020    source источник
comment
Я бы сказал, что std::list<S*> p; в порядке. Компилятору не должно быть проблемой генерировать указатель на структуру без ее макета/размера. ?   -  person Tony Tannous    schedule 23.07.2020
comment
Своего рода дубликат stackoverflow.com/questions/56975491/?   -  person Language Lawyer    schedule 23.07.2020
comment
@LanguageLawyer Нет, я специально выбрал list, потому что думал, что у него нет разрешения на использование неполных типов. Но ответ эорики предполагает, что это так. Тогда мне придется отредактировать вопрос.   -  person cigien    schedule 23.07.2020
comment
@LanguageLawyer Отредактировал вопрос, чтобы использовать контейнер, который не допускает неполные типы (насколько я могу судить).   -  person cigien    schedule 23.07.2020


Ответы (1)


std::deque<S> *p;   // seems to be UB like the previous case, 
                   // but is it ok if p is not used till S is defined?

Это на самом деле интересный бит здесь. Да, создание экземпляра этого контейнера с неполным типом не допускается, это не предусмотрено. Но возникает вопрос, действительно ли он создан. Согласно основному языку, это не обязательно.

[temp.inst]

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

Указатель на тип не требует, чтобы тип был полным. Таким образом, одного этого объявления обычно недостаточно для создания экземпляра шаблона класса, и поэтому может быть преждевременно определять, что требование контейнера здесь нарушено.

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

Так что, чтобы ошибиться в сторону осторожности, я бы тоже подумал об этом UB.


std::deque<S*> p;  // not really sure about this one

Это хорошо. Независимо от того, является ли S полным, S* по-прежнему является полным типом объекта. Я говорю это, потому что это не включено в

[основные.типы]

5 Класс, который был объявлен, но не определен, перечисление type в определенных контекстах ([dcl.enum]) или массив неизвестного связанного или неполного типа элемента является не полностью определенным типом объекта. Неполностью определенные типы объектов и cv void являются неполными типами ([basic.fundamental]). Объекты не должны иметь неполный тип.

Ограничения на полноту S появляются только при попытке использовать такой указатель в выражениях, выполняющих разыменование или арифметику указателя. Но сам тип указателя все еще завершен. Так что это допустимый аргумент шаблона для типа контейнера.

person StoryTeller - Unslander Monica    schedule 23.07.2020
comment
Я не уверен, что вы подразумеваете под преждевременным определением... Это определенно нормально, или реализация может отклонить это? - person cigien; 23.07.2020
comment
@cigien - Ну, я прочитал когда полнота типа класса влияет на семантику программы как довольно широкое. Можно утверждать, что полнота этого типа влияет на семантику программы. - person StoryTeller - Unslander Monica; 23.07.2020
comment
Я, конечно, думаю, что корректность программы связана с сематикой программы. ИМО формулировка подразумевает, что это нормально, но я в основном угадываю здесь. - person cigien; 23.07.2020
comment
@cigien - Ну, я резюмировал свои размышления в последнем редактировании. - person StoryTeller - Unslander Monica; 23.07.2020
comment
Спасибо, так лучше. Я всегда предпочитаю ответы, которые отстаивают свою точку зрения, правильно это или неправильно :) - person cigien; 23.07.2020