Why std:: is not needed when using ispunct() in C+

2020-08-12 09:38发布

问题:

#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;
}

It seems that I can use ispunct() without std:: or declaring using std::ispunct; but I can't do that with std::cout or std::cin. Why is this happening?

回答1:

It means ispunct is part of the global namespace, rather than the std namespace. This is probably because ispunct is one of the functions brought over from C (hence it is in cctype).

On the other hand, cout and cin are part of the std namespace, not the global namespace.

Edit:

As to why things from C are in the global namespace instead of in the std namespace, I believe it has to do with allowing C code to compile by a C++ compiler with minimal changes, since C++ aims to be compatible with C.

According to the comments, ispunct is allowed, but not required, to be in the global namespace (but is required to be in the std namespace), in <cctype>. However, if you had included <ctype.h> instead, ispunct would be required to be in the global namespace.



回答2:

C names (those you get from including a xxx.h header from C) are allowed to be in the global namespace in addition to the ::std namespace even if you are including the cxxx version of the header. This has been done because it can be a problem not to have those in the global namespace if you provide the C++ implementation, but not the C implementation (so the actual C headers are from a compiler you don't control).

In your case, ispunct comes from the header ctype.h. While you are including the cctype header, this in turn includes the ctype.h header which declares the symbol ispunct in the global namespace.



回答3:

C++ headers derived from C (such as <cctype>) are required to put the names of things that they declare in the namespace std and they are permitted to also put them in the global namespace. Formally, this wasn't allowed until C++11, but the old rule that those headers were not allowed to put names into the global namespace could not be implemented reasonably and was commonly ignored.



标签: c++ std