Reputation: 22143
For example in foo.h
:
typedef struct foo_t foo_t;
/* Lots of function declarations dealing with foo_t... */
int foo_print(const foo_t *foo); /* Print foo to stdout. */
int foo_fprint(FILE *f, const foo_t *foo); /* Print foo to file f. */
I don't want to litter foo.h
with too many other header files that users of foo.h
might not have wanted to include, but I do need to declare functions that take types such as FILE*
. I doubt that I am the first to encounter this dilemma, so what do people usually do in these circumstances? Or am I misguided in wanting to avoid including stdio.h
in my header files?
EDIT:
People seem not to be understanding my question. To clarify, here are some potential solutions:
stdio.h
and not worry about it causing conflicts in my clients' code (such as if they happened to have their own function that happened to be called getchar
).#ifdef
to find out if stdio.h
had already been included, and only then declare the FILE*
-related functions. The downside of this is that it would impose a particular ordering to #include
s in my clients' code.foo_io.h
.What question is what is the best thing to do?
Upvotes: 6
Views: 3982
Reputation: 96291
If you're using a standard library functionality, just include that standard header full stop. Don't try to over-think that someone may have a function with the same name as something in the standard library: Their code is already fragile/broker and you shouldn't worry about such cases.
I can't make out if your code is C++ or C though (note that even though C++ may have roots in C they are distinct languages). If it's C++ you can use cstdio
instead of stdio.h
and use features from the std
namespace instead of the global namespace. Otherwise if your code is C you have to use stdio.h
Upvotes: 0
Reputation: 7068
You've already answered your own question. Both 1) and 3) are valid solutions. If you use FILE*
in one of your functions then it only makes sense to use your function in combination with the header where FILE
is declared. As others noted, there is no header that would forward declare FILE
, so your only choice is to include stdio.h
.
If your client includes your header file, assume that all the functions will be used. Do not use conditional compilation for cutting out include's. If I'd include your header file and see that that it contains a declaration of a function that uses FILE*
I would expect to have stdio.h
included as well.
Upvotes: 0
Reputation: 1916
Refering to the updated question:
Conditionally enabling or disabling blocks of code (or features) depending on order of included files stinks as hell. It's a straight way to hell.
If you want to enable or disable your functionality, making your code more modular, you can use preprocessor macros, possibly requiring user to explicitly choose compilation mode.
#ifdef USE_STDIO
#include <stdio.h>
#endif
lotsa lotsa code
#ifdef USE_STDIO
int foo_print(const foo_t *foo);
int foo_fprint(FILE *f, const foo_t *foo);
#endif
Downside of this solution: code becomes harder to follow.
Second option is to extract those methods to foo_io.h
(and possibly foo_io.c
). The downside of this solution is that you're forcing user to include two files instead of one.
Upvotes: 1
Reputation: 35454
You should strive to have header files compile cleanly in an empty source module. For example:
#include "myheader.h"
and that's it. If you put that in a C++ source file and compiled it with no other code, you should get no compiler errors.
If you do get errors, then you need to justify why there are errors. The only legitimate reason I would think of for errors is that the header is internal in your library, and was not meant to be used standalone by the user of your library.
If the header is supposed to be used by your clients, do not "fix" the problem by taking the test source file above and adding headers to the source. You fix it by including the proper headers within (in my simple case) myheader.h
Upvotes: 2
Reputation: 1916
Short answer: you are trying to solve a non-existing problem.
If you use FILE
, you include stdio.h
or cstdio
in C++. It's that simple.
Trying to "optimize" #include
s, besides obvious cases of unused ones, will not buy you anything and cause problems.
Upvotes: 3