Разрешено ли реализациям добавлять публичных членов к стандартным типам?
Разрешены ли стандартные реализации библиотек С++ для добавления общедоступных (и защищенных) элементов к интерфейсам стандартных типов? N3797 17.6.5.5 [member.functions]/2 говорит:
Реализация может объявлять дополнительные не-виртуальные сигнатуры функций-членов внутри класса:
- путем добавления аргументов с значениями по умолчанию в подпись функции-члена; [Примечание. Реализация может не добавлять аргументы со значениями по умолчанию для виртуальных, глобальных или не-членов. - конечная нота]
- путем замены сигнатуры функции-члена стандартными значениями на две или более подписи функций-членов с эквивалентным поведением; и
- путем добавления сигнатуры функции-члена для имени функции-члена.
Означает ли это, что стандартная библиотека не может добавлять каких-либо дополнительных публичных пользователей с именами, не упоминаемыми в стандарте ни при каких обстоятельствах (включая, например, зарезервированные идентификаторы)?
Небольшое объяснение: это текст о добавлении подписей (который, я предполагаю, говорит о новых подписях только для функций, которые уже определены там, поэтому нет новых имен), которые мне удалось найти в стандарте. Существует также сноска 189, в которой говорится:
Действительная программа на С++ всегда вызывает функцию ожидаемого библиотечного элемента или одну с эквивалентным поведением. Реализация также может определять дополнительные функции-члены, которые иначе не могли бы вызываться действительной программой на С++.
Весь этот текст исходит из [member.functions], поэтому он явно касается только функций-членов. Мой вопрос более общий и запрашивает любые ссылки, которые я мог пропустить: стандартная реализация библиотеки позволяет добавлять новые имена в общедоступные (и/или защищенные) интерфейсы стандартного типа, будь то данные или члены функции?
Ответы
Ответ 1
Я считаю, что у вас есть то, что вам нужно, с сочетанием нотной записки 189
, которая гласит:
Действительная программа на С++ всегда вызывает функцию ожидаемого библиотечного элемента или одну с эквивалентным поведением. Реализация также может определять дополнительные функции-члены, которые иначе не могли бы вызываться действительной программой на С++.
и раздел 17.6.5.11
Производные классы, которые гласят:
Реализация может выводить любой класс в стандартной библиотеке С++ из класса с именем, зарезервированным для реализации.
но не добавляет никаких ограничений, т.е. не позволяет ограничивать квалификаторы доступа и т.д.
и мы можем видеть libstdc++ эффективно использует производные классы, например, в stl_vector.h. Хотя, насколько я вижу, libstdc++
, похоже, избегает добавления публичных элементов данных, но это, вероятно, больше для чистого дизайна.
Как минимум, это выглядит недооцененным, но если вы придерживаетесь чего-то похожего на стиль реализации libstdc++
, вы должны быть хорошими.
Ответ 2
Я думаю, что ключом к чтению сноски 189 является фраза would otherwise not be called by a valid C++ program
.
Помните, что для реализации зарезервированы идентификаторы, начинающиеся с символа подчеркивания, за которым следует большая буква (или содержащая два подряд подряд символа подчеркивания). (раздел 17.6.4.3.2)
Таким образом, реализации могут свободно добавлять публичные/защищенные функции-члены, которые названы таким образом.
Например, в libС++ std::vector
имеет защищенную функцию-член с именем __throw_length_error