Почему std:: не требуется при использовании ispunct() в С++?
#include <iostream>
#include <string>
#include <cctype>
using std::string;
using std::cin;
using std::cout; using std::endl;
int main()
{
string s("Hello World!!!");
decltype(s.size()) punct_cnt = 0;
for (auto c : s)
if (ispunct(c))
++punct_cnt;
cout << punct_cnt
<< " punctuation characters in " << s << endl;
}
Кажется, я могу использовать ispunct()
без std::
или объявлять using std::ispunct;
, но я не могу сделать это с помощью std::cout
или std::cin
. Почему это происходит?
Ответы
Ответ 1
Это означает, что ispunct
является частью глобального пространства имен, а не пространства имен std
. Вероятно, это потому, что ispunct
является одной из функций, возвращаемых из C (следовательно, она находится в cctype
).
С другой стороны, cout
и cin
являются частью пространства имен std
, а не глобального пространства имен.
Изменить:
Что касается того, почему вещи из C находятся в глобальном пространстве имен, а не в пространстве имен std
, я полагаю, что это связано с тем, что C-код компилируется компилятором С++ с минимальными изменениями, поскольку С++ стремится к совместимости с C.
В соответствии с комментариями ispunct
разрешено, но не требуется, чтобы находиться в глобальном пространстве имен (но требуется). в пространстве имен std
), в <cctype>
. Однако, если бы вы включили <ctype.h>
, ispunct
был бы обязательным, чтобы находиться в глобальном пространстве имен.
Ответ 2
С именами (те, которые вы получаете от включения заголовка xxx.h
из C) разрешено находиться в глобальном пространстве имен в дополнение к пространству имен ::std
, даже если вы включаете версию заголовка cxxx
. Это было сделано, потому что проблема не в том, чтобы иметь в глобальном пространстве имен, если вы предоставляете реализацию на С++, но не в реализации C (поэтому фактические заголовки C принадлежат компилятору, который вы не контролируете).
В вашем случае ispunct
поступает из заголовка ctype.h
. Хотя вы включаете заголовок cctype
, это, в свою очередь, включает заголовок ctype.h
, который объявляет символ ispunct
в глобальном пространстве имен.
Ответ 3
Заголовки С++, полученные из C (например, <cctype>
), должны помещать имена тех вещей, которые они объявляют в пространстве имен std
, и они разрешены также помещают их в глобальный Пространство имен. Формально это не разрешалось до С++ 11, но старое правило, согласно которому эти заголовки не могли помещать имена в глобальное пространство имен, не могло быть реализовано разумно и обычно игнорировалось.