Почему нет заголовка ‹stlfwd› и можно ли считать его отсутствие дефектом?

Стандартная библиотека включает заголовок <iosfwd>, который (вперед) объявляет все потоки, включая любые typedef, и определяет шаблон char_traits, включая специализации.

К сожалению, нет такого заголовка <stlfwd>, который (вперед) объявляет все распространенные типы данных и функции STL, такие как vector, map, less, sort и т. д. Что еще более печально, пользовательский код не может добавлять такие объявления / typedef в пространство имен std. , согласно

§17.4.3.1 [lib.reserved.names] p1:

Для программы C++ не определено добавлять объявления или определения в пространство имен std или пространства имен в пределах пространства имен std, если не указано иное. Программа может добавлять специализации шаблонов для любого шаблона стандартной библиотеки в пространство имен std.

Да, это охватывает случай (прямых) объявлений, даже если типы уже существуют в стандартной библиотеке. Конечно, большинство (все?) компиляторов будут вести себя совершенно нормально, даже если добавить такие объявления, но, строго говоря, с точки зрения юриста, это поведение undefined. Я нахожу это особенно утомительным для typedefing стандартных контейнеров, таких как:

// how to forward declare map and string?

typedef std::map<std::string, std::string> Attributes;

Теперь можно ли это считать недостатком?

Я имею в виду как отсутствие заголовка <stlfwd> (а лучше <stdfwd>, перекрывающего и <iosfwd>), так и запрет на уже существующие в стандартной библиотеке объявления.

Кроме того, в соответствии с этот вопрос, если один (вперед) объявляет стандартный контейнер, алгоритмы и функторы/функционалы именно так, как того требует стандарт, код должен быть полностью валидным (если бы не запрет пользовательских объявлений в пространстве имен std), потому что реализациям не разрешено добавить любые скрытые/по умолчанию параметры шаблона.

Я спрашиваю об этом, потому что думаю о том, чтобы в конечном итоге отправить отчет о дефекте по этому поводу.


person Xeo    schedule 11.06.2011    source источник
comment
Будет ли такой заголовок действительно полезен?   -  person James McNellis    schedule 11.06.2011
comment
@James McNellis Да, это означало бы, что компиляторам не нужно будет тратить время на повторный анализ полного определения STL для единиц компиляции, которые используют STL только по указателю или ссылке. Это уменьшит физическую зависимость между STL и клиентским кодом, а это означает, что изменение реализации STL потребует перекомпиляции меньшего количества клиентского кода.   -  person Mankarse    schedule 11.06.2011
comment
@Mankarse Я бы сказал, что изменения в реализации стандартной библиотеки настолько редки, что принудительная перекомпиляция не является реальной проблемой. Но не могли бы вы подробнее остановиться на первом пункте? Мне просто трудно представить реальный сценарий, когда вам не понадобится полное определение, если оно вам вообще понадобится в единице перевода.   -  person Mark B    schedule 11.06.2011
comment
@Mankarse: Если бы реализация стандартной библиотеки изменилась, я бы не стал доверять компилятору, чтобы он не выполнял полную перекомпиляцию. Даже если это вызывает беспокойство, для этого и нужны предварительно скомпилированные заголовки. Тем не менее, я сомневаюсь, что будет существенная выгода: стоимость лексирования и анализа пары заголовков почти наверняка ничтожна по сравнению со стоимостью остального процесса компиляции (особенно если учесть создание экземпляра шаблона). (Однако у меня нет этой проблемы; 99,9% моего кода все равно оказывается в заголовках, поскольку я следую правилу, если это не шаблон, это не должно быть достаточно общим правилом)   -  person James McNellis    schedule 11.06.2011
comment
Принята точка @Mark B - это довольно редко, но неудобно и непоследовательно в тех случаях, когда это происходит. Трудно описать ненадуманный пример в 500 символов, но я могу представить как минимум 2 ситуации. 1) у вас есть класс, который создается одной частью программы из стандартного контейнера, но используется в другой части без знания этого контейнера (было бы лучше использовать Итераторы, я знаю, но представьте, что это в разделяемой библиотеке) . 2) У вас есть класс, созданный фабрикой, фабрика берет стандартный контейнер по ссылке и передает его.   -  person Mankarse    schedule 11.06.2011
comment
@James McNellis - я полностью согласен со всем, что касается философии шаблонов, но, работая над устаревшей системой с общим временем перекомпиляции в несколько часов, я могу сказать вам, что физические зависимости действительно становятся важными для больших систем.   -  person Mankarse    schedule 11.06.2011


Ответы (1)


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

Это оставляет нас с типами контейнеров. Определенно есть случаи, когда их предварительное объявление было бы полезно, но я подозреваю, что было просто решено, что, поскольку определение каждого контейнера относительно простое (по сравнению с iostreams), было бы предпочтительнее просто использовать полное включение, а не включение ‹containerfwd> Например.

person Mark B    schedule 11.06.2011
comment
Проблема возникает, в частности, с определением типов стандартных контейнеров. Скажем, вы хотите typedef std::map<std::string,std::string> Attribues;, как бы вы объявили об этом? :/ - person Xeo; 11.06.2011
comment
@Xeo: я думаю, что смысл Марка в том, что вы просто не объявляете об этом. - person Billy ONeal; 11.06.2011
comment
@Xeo - если вам нужно предварительно объявить это, используйте не typedef, а, возможно, struct Attributes, который можно будет разработать позже в другом модуле. - person Bo Persson; 11.06.2011