0

I want to print to standard output from my program. But when I include <iostream>, many other functions are injected directly into the global namespace.

#include <iostream>

int main() {

    std::cout << "test";

    getc(0); // visible WITHOUT namespace
    getchar(); // visible WITHOUT namespace
}

Is there any way to hide unnecessary functions from standard headers?

I need to hide these functions because I can't create my own functions with similar names, and also it clogs up Intellisense suggestions.

11
  • 10
    Why? Just implement your functions in your own namespace and then use yournamespace:: to call your functions. Always be explicit. Commented Dec 17, 2023 at 13:25
  • 1
    Related maybe: How to hide functions in C++ header files Commented Dec 17, 2023 at 13:29
  • 1
    I think this is impossible. I vaguely remember some standard library implementation which doesn't have this problem (you could theoretically use it instead of your current implementation) but I don't remember any details — I can't change my implementation anyway. Commented Dec 17, 2023 at 13:52
  • 1
    "because I can't create my own function with a similar name" -- you can name your functions even exactly the same as the global ones, as long as you put them into your custom namespace, as mentioned in the first comment. Good practice is to use custom namespaces anyway, even when there's no conflict (yet). Commented Dec 17, 2023 at 13:54
  • 2
    Is there are any way to hide unnecessary functions from std headers? Yes, there is a way. You'd need to write your own standard headers that don't pollute the global namespace. Alternatively, C++20 has modules (but you'll need C++23 for modules of the standard C++ library). Commented Dec 17, 2023 at 14:03

2 Answers 2

1

C++ is (somewhat) compatible with C. Furthermore, C++ uses C header files and standard C library functions for most interactions with the operating system. In particular, getc() and getchar() are both defined in the header file stdio.h, which can be indirectly included from iostream (depends on implementation, but yours does).

According to the C++ standard, you are forbidden from using ANY name from the standard C library in global context: Resolution of overloaded extern C function with default arguments

Nonetheless, just overriding those functions from the C standard library in your own C++ code just works, as the above link also demonstrates. But you shouldn't rely on that feature. Better use a private namespace for your app and be safe.

Sign up to request clarification or add additional context in comments.

2 Comments

"just overriding those functions from the C standard library in your own C++ code just works" - it get compilation problem, when I try to pass overloaded function by pointer.
@user3324131 To get a pointer to an overloaded function, you need to use one of the available methods to select the right overload. More information about that here: stackoverflow.com/questions/2942426/…
1

EDIT

(this answer has been completely rewritten in spite of further analysing the posted code)

Before continuing to read, please read this answer that will probably answer your question better than I explain it here.

After your comment, functions appear to be also in the default global namespace. This is normal when you employ C code in your programs, because C has no idea of namespaces, so it is very frequent (and the standard allows it, as said in the cited answer) to consider the standard C functions to be included in both namespaces. But seeing what happens when running your code is a completely unrelated error, as you call getc(0) which is undefined behaviour (this in plain C too) because you pass NULL for the FILE * pointer required by the function. At least in my system, your program crashes.

$ pru
Segmentation fault (core dumped)

so I included the necessary <cstdio>

#include <iostream>
#include <cstdio>

int main() {

    std::cout << "test";

    /* yes, visible but most probably not the function you want to be
     * called, as you are using one function declared in C++
     * <iostream> package, and not in <cstdio> */
    getc(stdin); // visible WITHOUT namespace
    getchar(); // visible WITHOUT namespace
}

Which resulted strangely in errors about the declaration of getc() (as it is passed a 0 integer value, while requiring a FILE * pointer)

I had to change the 0 to stdin (or std::stdin ???) in order to call properly the function getc(). So, how could you get your code actually running properly in C++ without the inclussion of the <cstdio> header, is a mistery for me (probably, but not sure it is included from <iostream> in some way). In C++ all functions need to be declared before using them... If you want to use getchar() or fgetc(), or getc(), you need to #include the appropiate file (in this case <cstdio> and not <iostream>) or both, but if you include only the <iostream> one, probably you are calling another, different, C++ functions that is not the one you are trying to call (or you are invoking a macro, see below).

You don't include <cstdio> in your posted code, so I cannot guess why you don't get an error from the compiler, as getc() and getchar() require that include file (in C++, includes ---more precisely, function declarations--- are required before use, not optional, they never default as it was common in C) and C functions do require the extern "C" directive to be used by the compiler (if not done, the linker will complain not finding the C++ mangled function name, as the parameter types must be encoded in the external identifier to do appropiate select of overloaded functions). Possibly, you have found a valid getc(int); function (not the one in C which should be something similar to extern "C" int getc(FILE *); instead) Probably the inclusion of <cstdio> happens anywayt, just leaking some names to the global namespace. I cannot say, as I have not found getc or getchar in the file istream (but probably they are defined as macros included from there on).

BTW Of course, your std::cout << "test"; doesn't show because cout is buffered (line buffered, and you casually don't use a new line at the end of test message, this kind of error is so common that all new C/C++ books should talk about it), and the SIGSEGV occurs before it has had the opportunity to flush its buffers. I think this is the error you have, and not the problems you are stating in the question, with the std namespace that seems that <cstdio> puts also its definitions in the global namespace.

Try this:

#include <iostream>
#include <cstdio>

int main() {

    std::cout << "test";

    /* use a valid parameter here, and not what you are using */
    getc(stdin); // visible WITHOUT namespace
    getchar(); // visible WITHOUT namespace
}

and you will see that everything works fine, no SIGSEGV and fine!!!

As a rule, consider that standard C functions will never be defined in a specific namespace, as they are just plain C functions, and C functions are not namespace aware. So, despite the compiler considers and puts them in some namespace, think that this is because the function writer is aware that the function will be used in C++ environments, which is something recommended only for legacy software and deprecated in new designs. The normal case is that the function is used in C++ because it already exists (this was the original compatibility reason of making C++ backwards compatible with C) but has not been written to be a C++ namespace aware function.

If you want to run free of problems in C++, just put everything you code in your own namespace, and so, everything will be clear to the compiler. This is the correct use of namespaces, and not the opposite.

One last comment. stdio frequently offers two versions of the most frequently used functions (in particular both getc() and getchar()) as preprocessor macros (neither the C preprocessor nor the C++ one uses namespaces in macro names, when expanding those macros into equivalent code, but do on the expanded code ---to avoid name clashes---) and as plain functions, so it can also be a consequence unexpected for your code. In plain C this has no consequence, but having more efficient code, avoiding an extra function call. But in C++ using macros as function inlining is a bit dangerous, as namespaces have not been included in the C++ preprocessor.

IMHO, what is happening here is that getc() and getchar() are both #defined somewhere and they are expanded in valid C code (if they use the namespace or not, after expansion is implementation dependent) and of course, you will probably not be able to consider using std::getc() or std::getchar() as they are not C++ functions at all (they should be capable to compile and run in a non C++ aware C compiler) and expanded into non namespace aware function calls... and so the compiler has to put them in the global namespace, because they never were namespace included.

2 Comments

I changed #include <iostream> to #include <cstdio>. std::cout is no more visible, but getc and getchar still in global space. So this answer is now work for me unfortanly.
@user3324131, please reread the answer that has been completely rewritten, based on more digging into your code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.