Несовместимое внедрение пространства имен для заголовков средств библиотеки C

Я играл с ptrdiff_t и чтение стандарта C ++ 11, когда я столкнулся с этой «проблемой». Во-первых, факты:

Тип ptrdiff_t (только пример) взят из заголовка библиотеки Standard C <stddef.h> в <cstddef> (§18.2 / 2). В разделе 17.6.1.2 говорится, что объявления, извлеченные из стандартной библиотеки C, будут находиться внутри std Пространство имен:

Однако в стандартной библиотеке C ++ объявления (за исключением имен, которые определены как макросы в C) находятся в пределах пространства имен (3.3.6) пространства имен std, это
не указано, будут ли эти имена сначала объявлены в глобальной области пространства имен, а затем введены в пространство имен std явным с помощью деклараций (7.3.3).

Как также сказано, объявления могут быть сначала объявлены в глобальном пространстве имен, а затем внедрены в std, Таким образом, для моей реализации будет иметь смысл, что следующее компилируется просто отлично:

#include <cstddef>

int main(int argc, const char* argv[])
{
std::ptrdiff_t x;
ptrdiff_t y;
return 0;
}

Моя реализация (gcc 4.6.3) должна была объявить ptrdiff_t в глобальном пространстве имен, а затем внедрил его в std, Однако, если я скомпилирую следующий код, я получаю сообщение об ошибке (обратите внимание на <iostream> включают):

#include <iostream>

int main(int argc, const char* argv[])
{
std::ptrdiff_t x;
ptrdiff_t y;
return 0;
}

main.cpp: в функции int main (int, const char **) ’:
main.cpp: 6: 3: ошибка: «ptrdiff_t» не был объявлен в этой области
main.cpp: 6: 3: примечание: предлагаемые альтернативы:
/usr/include/c++/4.6/i686-linux-gnu/./bits/c++config.h:156:28: примечание: ‘std :: ptrdiff_t’

Итак, с std::ptrdiff_t доступен, <iostream> должно быть в том числе <cstddef> каким-то образом (хотя это не обязательно). Но почему глобальная версия также недоступна?
был раньше? Могу ли я не ожидать, что эта инъекция будет последовательной, даже если это фактически тот же заголовок? Это кажется странным поведением. Может ли произойти инъекция, может быть не определено, но это должно быть, по крайней мере, так или иначе, а не оба, верно?

1

Решение

Не полагайтесь на один заголовок, включая другой, если вы хотите, чтобы что-то было объявлено / определено в определенном заголовке, вы должны включить его.

Для приведенного вами примера с g ++ на самом деле есть два определения ptrdiff_t (а также size_t в этом отношении). Во-первых, в namespace std, что исходит от <bits/c++config.h>, И тот, в глобальном пространстве имен от <stddef.h> (так что <cstddef>).

3

Другие решения

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

     #include <cstddef>

вместо. Однако вы используете

        #include<iostream>

И это имеет определение «std :: ptrdiff_t» в нем косвенно. Однако глобальный «:: ptrdiff_t» не определен в «iostream», и «iostream» не включает «cstddef», как вы думали. Вместо этого «iostream» включает «бит / c ++ config.h». Фактический «std :: ptrdiff_t» определен в этом файле.

Если вы посмотрите на содержимое файла «cstddef», то увидите, что там всего две «полезные» строки

Кстати, вышеприведенное обсуждение относится к GCC 4.6 и GCC 4.7. Для GCC 4.4 «iostream» напрямую включает «cstddef», поэтому ptrdiff_t будет доступен в обоих пространствах имен (std и global).
#включают
#включают

Последняя строка содержит глобальный «:: ptrdiff_t», а первая определяет пространство имен std.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector