Подтвердить что ты не робот

Являются ли функции 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 (но не указывают другие области, в которых они находятся).

4b9b3361

Ответ 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 С++, В таком случае эти гарантии не могут быть сделаны. Я был бы удивлен, если такая реализация будет запрещена как совместимая реализация.