Являются ли функции C, объявленные в заголовках <c ____> гарантированно находящимися в глобальном пространстве имен, а также std?
Итак, это то, о чем я всегда думал, но никогда не был уверен. Так что это исключительно вопрос любопытства, а не настоящая проблема.
Насколько я понимаю, когда вы делаете что-то вроде #include <cstdlib>
, все (кроме макросов, конечно) объявляются в пространстве имен std::
. Каждая реализация, которую я когда-либо видел, делает это, делая следующее:
#include <stdlib.h>
namespace std {
using ::abort;
// etc....
}
Что, конечно, влияет на то, что вещи находятся как в глобальном пространстве имен, так и в std
. Гарантировано ли это поведение? Или возможно, что реализация может помещать эти вещи в std
, но не в глобальное пространство имен? Единственный способ, который я мог бы сделать, это сделать, чтобы ваш libstdС++ реализовал каждую функцию c, помещая их непосредственно в std
, вместо того, чтобы просто включать существующие заголовки libc (потому что нет механизма для удаления чего-либо из пространства имен). Это, конечно, много усилий, при этом мало пользы.
Суть моего вопроса в том, что следующая программа строго соответствует и гарантированно работает?
#include <cstdio>
int main() {
::printf("hello world\n");
}
РЕДАКТИРОВАТЬ: Ближайший я нашел это (17.4.1.2p4):
За исключением случаев, указанных в пунктах 18 - 27, содержимое каждого заголовка cname должны быть такими же, как у соответствующий заголовок name.h, as указанных в ИСО/МЭК 9899: 1990 Языки программирования C (раздел 7) или ISO/IEC: 1990 Языки программирования-C ПОПРАВКА 1: C Целостность, (п. 7), при необходимости, как бы включив. В стандартная библиотека C + +, однако, декларации и определения (кроме имен, которые определены как макросы в C) находятся в пространстве имен scope (3.3.5) пространства имен std.
что, честно говоря, я мог бы толковать в любом случае. "содержимое каждого заголовка cname должно совпадать с содержимым соответствующего заголовка name.h, как указано в ISO/IEC 9899: 1990 Языки программирования C", говорит мне, что они могут потребоваться в глобальном пространстве имен, но "В Стандартная библиотека C + +, однако, декларации и определения (кроме имен
которые определены как макросы в C) находятся в области пространства имен (3.3.5) пространства имен std. "говорит, что они находятся в std (но не указывают другие области, в которых они находятся).
Ответы
Ответ 1
Вот хороший обзор ситуации (с некоторой относительностью в сравнении с тем, что говорит стандарт) от Stephan T. Lavavej из команды MSVC (http://blogs.msdn.com/vcblog/archive/2008/08/28/the-mallocator.aspx#8904359):
>
также следует использовать <cstddef>
, <cstdlib>
и std::size_t
и т.д.
Раньше я был очень осторожен в этом. У С++ 98 был великолепный сон, в котором <cfoo>
объявлял бы все в пространстве имен std, а <foo.h>
включал бы <cfoo>
, а затем перетаскивал все в глобальное пространство имен с использованием-declarations. (Это D.5 [des.c.headers].)
Это игнорировалось многими разработчиками (некоторые из которых имели очень небольшой контроль над заголовками стандартной библиотеки C). Итак, С++ 0x был изменен, чтобы соответствовать реальности. Начиная с рабочего документа N2723, http://open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2723.pdf, теперь <cfoo>
гарантированно объявит все в пространстве имен std и может или не может объявлять вещи в глобальном пространстве имен. <foo.h>
- это противоположное: гарантировано объявить все в глобальном пространстве имен и может или не может объявлять вещи в пространстве имен std.
В реальности и в С++ 0x, в том числе <cfoo>
, не защищает от всех попыток, объявленных в глобальном пространстве имен. Вот почему я перестаю беспокоиться о <cfoo>
.
Это была проблема библиотеки 456, http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#456.
(С++ 0x по-прежнему обесценивает заголовки из стандартной библиотеки C, что весело.)
Я никогда не любил заголовки <cfoo>
и обнаружил, что всегда использую <foo.h>
. Теперь я чувствую, что могу перестать беспокоиться о моем недостатке С++ "чистоты" в этом отношении.
Ответ 2
В настоящее время нет. На самом деле, даже несмотря на то, что код будет работать с каждым компилятором, с которого я сейчас работаю, он действительно не должен работать вообще - #include
в одном из заголовков c * только предполагается предоставить вам доступ к именам внутри пространства имен std.
Поскольку реализация этого была такой болью (получение правильной по существу необходимости дублирования всей библиотеки C как библиотеки С++ в правом пространстве имен), в С++ 0x они немного изменили требования - теперь ваш код разрешен (хотя бы в случае использования памяти) все равно не требуется работать.
Ответ 3
Я не могу говорить о стандартах, поскольку я их не читал, но можно было представить среду С++, которая не построена поверх среды C, или где среда C является уровнем совместимости поверх базовых API С++, В таком случае эти гарантии не могут быть сделаны. Я был бы удивлен, если такая реализация будет запрещена как совместимая реализация.