Может кто-нибудь объяснить, пожалуйста, следующее:
$ cat test.cpp
#include <string>
std::string div;
$ g++ -c test.cpp
$ g++ -std=c++11 -c test.cpp
test.cpp:2:13: error: 'std::string div' redeclared as different kind of symbol
In file included from /usr/include/c++/4.7.1/cstdlib:66:0,
from /usr/include/c++/4.7.1/ext/string_conversions.h:37,
from /usr/include/c++/4.7.1/bits/basic_string.h:2814,
from /usr/include/c++/4.7.1/string:54,
from test.cpp:1:
/usr/include/stdlib.h:787:14: error: previous declaration of 'div_t div(int, int)'
$
Не должен div
символ быть в std
пространство имен также для режима C ++ 11? Или это что-то особенное для моей системы?
/usr/include/stdlib.h
Каждое имя в .h
Заголовок C stdlib находится в глобальном пространстве имен (очевидно).
Кроме того, любой cHEADER
Заголовок C ++ stdlib определит соответствующие имена из HEADER.h
в std
пространство имен, но также разрешено иметь их в глобальном пространстве имен (так что они могут просто сделать
// cHEADER
#include <HEADER.h>
namespace std{
using ::one_name_from_HEADER;
using ::another_name_from_HEADER;
// and so on...
}
и покончим с этим).
§D.5 [depr.c.headers]
p2 Каждый заголовок C, каждый из которых имеет имя вида
name.h
, ведет себя так, как будто каждое имя помещено в стандартное пространство имен библиотекиcname
заголовок помещается в глобальную область имен. Не указано, были ли эти имена сначала объявлены или определены в пределах области имен (3.3.6) пространства имен std, а затем введены в глобальную область имен с помощью явных объявлений using (7.3.3).p3 [ Пример: Заголовок
<cstdlib>
несомненно, предоставляет свои объявления и определения в пространстве имен std. Он также может предоставлять эти имена в глобальном пространстве имен. Заголовок<stdlib.h>
несомненно, обеспечивает те же объявления и определения в глобальном пространстве имен, что и в стандарте C. Он также может предоставлять эти имена в пространстве имен std. — конец примера ]
Как видите, то же самое верно и наоборот (<HEADER.h>
май вводит имена в std
пространство имен, как будто
// HEADER.h
#include <cHEADER>
using std::one_name_from_HEADER;
using std::another_name_from_HEADER;
// and so on...
}
), что делает различие между этими заголовками довольно … бесполезным, на самом деле.
div
это функция от <stdlib.h>
,
В C ++ 11 <c
вздор>
заголовкам было разрешено размещать вещи в глобальном пространстве имен.
C ++ 11 §17.6.1.2 / 4:
«За исключением случаев, указанных в пунктах 18–30 и Приложении D, содержание каждого заголовкаcname
должно быть таким же
как у соответствующего заголовкаname.h
, как указано в стандартной библиотеке C (1.2) или C Unicode TR, в зависимости от случая, как если бы это было сделано путем включения. В стандартной библиотеке C ++, однако, объявления (за исключением
имена, которые определены как макросы в C), находятся в пределах области имен (3.3.6) пространства именstd
, это
не указано, будут ли эти имена сначала объявлены в глобальной области имен, а затем введены
в пространство имен STD явным с помощью деклараций (7.3.3) «.
Отражение реальности распространенных реализаций C ++.
Так что, на самом деле, ничего не изменилось, кроме формального: то, что вы видите, теперь наказывается стандартом, а не является артефактом реализации, который нужно учитывать.
Кроме того, формальное изменение облегчает спор о том, что лучше .h
заголовки, а не c
ххх заголовки …
17.6.4.3.3 / 1 гласит:
Каждое имя, объявленное как объект с внешней связью в заголовке, зарезервировано для реализации, чтобы обозначить этот объект библиотеки с внешней связью,182 оба в пространстве имен
std
и в глобальном пространстве имен.
div
это имя, объявленное как функция с внешней связью в заголовке cstdlib, и, следовательно, зарезервированное имя в глобальном пространстве имен. Вам не разрешено использовать это имя.