I'm including header files which require certain pro-processor #defines to be present, however I do not want this to pollute the rest of my code e.g.:
// FOO may or may not already be defined here
#define FOO
#include "Bar.h"
#undef FOO
// FOO should be defined or not, as per the starting state
I'm thinking along the lines of:
#ifdef FOO
#define FOO_DEFINED
#endif
#define FOO
#include "Bar.h"
#ifndef FOO_DEFINED
#undef FOO
#else
#undef FOO_DEFINED
#endif
Questions:
Will the above work i.e. restore all macro definitions (or lack of) to the state they were in beforehand?
Is there perhaps a simpler solution?
Does it matter if FOO was already defined when I #define it? Should I add another #ifndef to protect against this?
It appears that in your example, Bar.h cares only whether FOO is defined or not, and not the actual expression bound to it. Furthermore, if someone else (I presume your code example is, itself, in a header file) defines FOO and cares about the expression bound to it, you don't want to make the mistake of redefining FOO with an empty expression. If so, you might want to simplify:
#ifndef FOO
#define FOO
#define UNDEF_FOO
#endif
#include "Bar.h"
#ifdef UNDEF_FOO
#undef FOO
#endif
yes it should work.
I have #pragma push_macro/pop_macro("macro_name") in mind, but it might work only in gcc and MS VC++
yes, it matters, you'll get a warning if it is defined again with a different value. As you state, you can shield it with #ifndef.
Related
Suppose I have two data structures that reference each other. I want to put them into their separate header files like this:
// datastruct1.h
#ifndef DATA_STRUCT_ONE
#define DATA_STRUCT_ONE
#include <datastruct2.h>
typedef struct DataStructOne_t
{
DataStructTwo* two;
} DataStructOne;
#endif
and
// datastruct2.h
#ifndef DATA_STRUCT_TWO
#define DATA_STRUCT_TWO
#include <datastruct1.h>
typedef struct DataStructTwo_t
{
DataStructOne* one;
} DataStructTwo;
#endif
and I have a main function:
#include <datastruct1.h>
#include <datastruct2.h>
int main()
{
DataStructOne* one;
DataStructTwo* two;
}
However my compiler complains:
$ gcc -I. -c main.c
In file included from ./datastruct1.h:4,
from main.c:1:
./datastruct2.h:8:2: error: unknown type name ‘DataStructOne’
8 | DataStructOne* one;
| ^~~~~~~~~~~~~
Why is that? What can I do to fix this?
Why?
In order to understand why, we need to think like a compiler. Let's do that while analysing main.c line by line. What would a compiler do?
#include <datastruct1.h>: Put "main.c" aside (push to the stack of files being processed) and switch to "datastruct1.h"
#ifndef DATA_STRUCT_ONE: hmm, this is not defined, let's continue.
#define DATA_STRUCT_ONE: OK, defined!
#include <datastruct2.h>: Put "datastruct1.h" aside and switch to "datastruct2.h"
#ifndef DATA_STRUCT_TWO: hmm, this is not defined, let's continue.
#define DATA_STRUCT_TWO: OK, defined!
#include <datastruct1.h>: Put "datastruct2.h" aside and switch to "datastruct1.h"
#ifndef DATA_STRUCT_ONE: this is now defined, so go straigh to #endif.
(end of "datastruct1.h"): close "datastruct1.h" and pop current file from the stack of filles. What were I doing? Ahh, "datastruct2.h". Let's continue from the place where we left.
typedef struct DataStructTwo_t ok, starting a struct definition
DataStructOne* one; Wait, what is DataStructOne? We have not seen it? (looking up the list of processed lines) Nope, no DataStructOne in sight. Panic!
What happened? In order to compile "datastruct2.h", the compiler needs "datastruct1.h", but the #include guards in it "datastruct1.h" prevent its content from being actually included where it's needed.
The situation is symmetrical, so if we switch the order of #include directives in "main.c", we get the same result with the roles of the two files reversed. We cannot remove the guards either, because that would cause an infinite chain of file inclusions.
It appears that we need "datastruct2.h" to appear before "datastruct1.h" and we need "datastruct1.h" to appear before "datastruct2.h". This does not seem possible.
What?
The situation where file A #includes file B which in turn #includes file A is clearly unacceptable. We need to break the vicious cycle.
Fortunately C and C++ have forward declarations. We can use this language feature to rewrite our header files:
#ifndef DATA_STRUCT_ONE
#define DATA_STRUCT_ONE
// No, do not #include <datastruct2.h>
struct DataStructTwo_t; // this is forward declaration
typedef struct DataStructOne_t
{
struct DataStructTwo_t* two;
} DataStructOne;
#endif
In this case we can rewrite "datastruct2.h" the same way, eliminating its dependency on "datastruct1.h", breaking the cycle in two places (strictly speaking, this is not needed, but less dependencies is always good). Alas. this is not always the case. Often there is only one way to introduce a forward declaration and break the cycle. For ecample, if, instead of
DataStructOne* one;
we had
DataStructOne one; // no pointer
then a forward declaration would not work in this place.
What if I cannot use a forward declaration anywhare?
Then you have a design problem. For example, if instead of both DataStructOne* one; and DataStructTwo* two; you had DataStructOne one; and DataStructTwo two;, then this data structure is not realisable in C or C++. You need to change one of the fields to be a pointer (in C++: a smart pointer), or eliminate it altogether.
One way to resolve the circular dependency and still use the typedefs where possible is to split the headers into two parts with a separate guard macro for each part. The first part provides typedefs for incomplete struct types and the second part completes the declarations of the struct types.
For example :-
datastruct1.h
#ifndef DATA_STRUCT_ONE_PRIV
#define DATA_STRUCT_ONE_PRIV
/* First part of datastruct1.h. */
typedef struct DataStructOne_t DataStructOne;
#endif
#ifndef DATA_STRUCT_ONE
#define DATA_STRUCT_ONE
/* Second part of datastruct1.h */
#include <datastruct2.h>
struct DataStructOne_t
{
DataStructTwo *two;
};
#endif
datastruct2.h
#ifndef DATA_STRUCT_TWO_PRIV
#define DATA_STRUCT_TWO_PRIV
/* First part of datastruct2.h. */
typedef struct DataStructTwo_t DataStructTwo;
#endif
#ifndef DATA_STRUCT_TWO
#define DATA_STRUCT_TWO
/* Second part of datastruct2.h */
#include <datastruct1.h>
struct DataStructTwo_t
{
DataStructOne *one;
};
#endif
main.c
/*
* You can reverse the order of these #includes or omit one of them
* if you want.
*/
#include <datastruct1.h>
#include <datastruct2.h>
int main(void)
{
DataStructOne *one;
DataStructTwo *two;
}
As mentioned in the comment in main.c above, only one of the headers needs to be included since the other header will be included indirectly anyway.
Well, if both structures reference each other, it is clear that they must be related. The best thing you can do is to put both in one include file (as they are related) but putting them in different and making the compiler to read from one include the other will make the compiler to read the main file... .from main file start reading include A until it gets to the point to include B, and start reading B to the point of the include A again(we'll start reading A again in a recursive manner that has no end) you will never stop reading each file and worse, you will get an error the second time you see the same struct definition (because it has been already defined before)
To allow the user to include any or both files without a problem, a define is made when include file A is encountered:
File A.h
#ifndef INCLUDE_FILE_A
#define INCLUDE_FILE_A
/* ... the whole stuff of file A with the proper includes of other files.*/
#include "B.h"
#endif /* INCLUDE_FILE_A */
and in
File B.h
#ifndef INCLUDE_FILE_B
#define INCLUDE_FILE_B
/* ... the whole stuff of file B with the proper includes of other files.*/
#include "A.h"
#endif /* INCLUDE_FILE_B */
so the definitions made in file A are only used if INCLUDE_FILE_A has not been included previously, and skip them if file A has been included already (and the same for B.h, of course).
If you make the same on file B (but instead with INCLUDE_FILE_B) then you will be secure that both files will be included in either order (depending on how you did it in the first case) and will never be included again (making th e inclussion secure of returning back to the main file.
I have some code, that has namespace configurable by user as this:
#pragma once
#ifdef GRAPHICS_NAMESPACE
namespace GRAPHICS_NAMESPACE {
#endif
class Foo {
}
#ifdef GRAPHICS_NAMESPACE
}
#endif
And in cpp file, there is
#ifdef GRAPHICS_NAMESPACE
using namespace GRAPHICS_NAMESPACE;
#endif
Now I have a problem. I have defined -DGRAPHICS_NAMESPACE=Graphics and I have a header with:
#pragma once
#include "Foo.h"
class Bar {
Foo foo;
}
But Foo foo gives me error, since Foo is in namespace now named Graphics. I can solve this with adding
#ifdef GRAPHICS_NAMESPACE
using namespace GRAPHICS_NAMESPACE;
#endif
to my header, but that is not very safe since it will be using namespace everywhere where I include my header. Is there any other solution?
Although I would say this is not the optimal way to arrange things, I've seen worse and the solution to your problem is rather straightforward:
class Bar {
#ifdef GRAPHICS_NAMESPACE
GRAPHICS_NAMESPACE::
#endif
Foo foo;
}
If you insist on sticking with this design, you can clean this up, somewhat, by defining a 2nd macro:
#ifdef GRAPHICS_NAMESPACE
#define GRAPHICS_CLASS(x) GRAPHICS_NAMESPACE:: x
#else
#define GRAPHICS_CLASS(x) x
#endif
And then declare things along the lines of:
class Bar {
GRAPHICS_CLASS(Foo) foo;
}
Finally, if you insist on relying on the preprocessor for this kind of critical functionality, you may want to consider spending a little bit more time reading what your C++ book says on this topic. These are fairly basic, straightforward uses of the C++ preprocessor, which I expect should be fully explained in any introduction on what a C++ preprocessor is, and how it works.
I would do it like this:
#ifdef GRAPHICS_NAMESPACE
#define GRAPHICS GRAPHICS_NAMESPACE
#else
#define GRAPHICS
#endif
...
GRAPHICS::Foo
Since preprocessor don't report an error when checking value of preprocessor's symbol that isn't actually defined (usually due to the lack of #include "some_header.h"), I use this cumbersome three line construction with "defined":
#if !defined(SOME_SYMBOL)
#error "some symbol isn't defined"
#endif
#if SOME_SYMBOL == 1
// Here is my conditionally compiled code
#endif
And the way with "#ifndef" is the same.
Is there a more elegant way to perform this check?
In your construction you could use an else block to skip the check for defined:
#if SOME_SYMBOL == 1
// Here is my conditionally compiled code
#else
// error
#endif
But in principle the comments are right. #if !defined and the shorthand #ifndef are the two available versions.
Currently, you are checking if SOME_SYMBOL is equals to 1. Do you execute different code based on that value ?
If not, you could simply use:
#ifdef SOME_SYMBOL
// Here is my conditionally compiled code
#else
// error
#endif
And now it's a short step to the typical c++ include guards. Copying from that wikipedia link, here is a grandparent.h file:
#ifndef GRANDPARENT_H
#define GRANDPARENT_H
struct foo {
int member;
};
#endif /* GRANDPARENT_H */
Now, even if you end up including this header twice, it will only be executed once.
I am writing a class (separated in header file myClass.h and implementation file myClass.cpp) which I want to use with both standard C++ and the Qt framework. Since the differences in the code are very small (and I wanted to try it out once), I decided to #define USINGQT 1 in order to toggle the small sections of code via
#if USINGQT==1
//Qt code
#else
//standard code
#endif
Now I came to the conclusion that it'd be convenient to use QStrings throughout the whole class instead of std::strings when "activating" the USINGQT switch. However, the method above would render the code extremely messy. My solution (in the header file):
#if USINGQT==1
#include <QString>
#define string QString
#else
#include <string>
#define string std::string
#endif
Now to the question:
Consider the files to look like
---myclass.h-------------------------
#ifndef MYCLASS_H
#define MYCLASS_H
#define USINGQT 1 //1=on, else off
#if USINGQT==1
#include <QString>
#define string QString
#else
#include <string>
#define string std::string
#endif
namespace mySpace {
class MyClass {
string qtOrStd;
string foo();
//etc...
};
} //namespace
#endif //MYCLASS_H
-------------------------------------
---myclass.cpp-----------------------
#include "myclass.h"
using namespace mySpace;
//implementations
string MyClass::foo() //string symbol occurs, as does the USINGQT
-------------------------------------
Where is the correct place to #undef the string and USINGQT symbols? At the end of the header file (which would then require a redefinition and "undefinition" in the implementation file as well) or just at the end of the implementation file?
I should capitalize the string macro as well, shouldn't I...? >.>
If I put the macro definitions inside the namespace I receive approx. 800 error messages with entries like "no member of mySpace::std" among others. Can you say something about that without further information? Otherwise it compiles just fine.
EDIT: I may should have told you that I want the macros to only apply to this specific header AND its implementation file. Despite the fact that I will of course go for the typedefs - in the macro case, I'd guess, I should place the #undef at the end of the implementation file. Because the macros won't be redefined because of the include guards.
Firstly you do not need to toggle USINGQT by making it equal to 1 you can simply #define USINGQT and then use #ifdef USINGQT for your if statement.
In terms of your ability to toggle which string library you use I would suggest using a typedef alongside a pre-processor if statement. This would avoid any namespace issues. An example of this is shown below.
// -------------- Some config file -------------=
#define USINGQT
// -------------- MyClass.h --------------------=
// Header guard
#ifndef MyClass
#define MyClass
// Conditional Header types
#ifdef USINGQT
// QT OPTION
typedef QString my_string;
#else
// Not QT
typedef std::string my_string;
#endif
class MyClass {
public:
my_string some_string;
MyClass()
{
my_string = "hello world";
}
};
#endif
I do not see any reason to #undef the macro. Surely you want all your code to be compiled with one state of that macro? Then you will not need to #undef it.
However, I also strongly suggest you to use typedef for your string definition. This will anyway be clearer, you will not think about capitalizing it, and you can even put it into your namespace. Use :: if you need to access global namespace:
#define USINGQT
#ifdef USINGQT
#include <QString>
#else
#include <string>
#endif
namespace mySpace {
#ifdef USINGQT
typedef ::QString string;
#else
typedef ::std::string string;
#endif
}
Also note (as shown above) that if you need just a boolean value for macro, then you don't need to make it 1 or 0, just use #ifdef/#ifndef.
After this, in your .cpp, just use mySpace::string and never bother about macroses.
You don't have to #undef macros unless another file tries to re-define it. You can't #undef a macro before you're done using it and therefore, if you #define a macro in a header and want to use it in files that include the header, then you cannot #undef it in that header.
1) Where is the correct place to #undef the string and USINGQT symbols? At the end of the header file ...
Only if you use it in that header... but you apparently do use it a file that includes the header, so no.
or just at the end of the implementation file?
Undefining a macro at the end of an implementation file is pointless, because there will be no code after the end of the file to which the macro applies anymore. Just let it stay defined.
2) I should capitalize the string macro as well, shoudln't I...? >.>
You don't have to capitalize macros, but it's a convention. That said, defining a macro by the same name as a standard class is just asking for trouble. You should use a typedef instead of a macro here in order to get meaningful error messages in case of name conflicts. And use another name like string_t or define the typedef in a namespace.
3) If I put the macro definitions inside the namespace I receive approx. 800 error messages
The errors don't come from defining the macros inside a namespace. The errors come from using the macros as-if they were part of the namespace. For example, if you say:
namespace mySpace {
#define string std::string
}
mySpace::string s;
then the string will be replaced with std::string and the typename becomes mySpace::std::string. Since you haven't defined a std namespace inside mySpace, this is wrong. What you need to understand is that namespaces don't have any effect on preprocessor macros. Which makes it harder to avoid name conflicts which is one reason why you usually want to avoid pre-processor macros.
If the USINGQT macro applies to all of your code such that it must be same for all files, you may want to not define it in a header at all, but instead pass it as an argument to the compiler. That way you can easily compile with different values without changing a file.
About your edit:
Even if you want the macro to be defined differently in another file, then undefining it at the end of the implementation has no effect, because the implementation file won't be included by the files that include the header. You should avoid a situation where you need multiple, different definitions (or lack of definitions) of macros, but if you're in such a situation, then yes, your only solution is to define it separately in each file that needs it and then undefine at the end of any header that needs it. But you're not in a such situation because you can use a type alias instead.
#include "DLLDefines.h"
#include "DLLDefines.h"
The above actually passed compilation, but why?
Well, it's legal because it has to be legal. Because you often include the same header multiple times without even realizing it.
You might include two headers in a .cpp file, each of which include a number of files, some of which might be included by both.
For example, all the standard library headers (say, string or vector for example) are probably included in most of your headers. So you quickly end up with the same header being indirectly included multiple times in the same .cpp file.
So in short, it has to work, or all C++ code would fall apart.
As for how it works, usually through include guards. Remember that #include just performs a simple copy/paste: it inserts the contents of the header file at the #include site.
So let's say you have a header file header.h with the following contents:
class MyClass {};
now let's create a cpp file which includes it twice:
#include "header.h"
#include "header.h"
the preprocessor expands this to:
class MyClass {};
class MyClass {};
which obviously causes an error: the same class is defined twice. So that doesn't work. Instead, let's modify the header to contain include guards:
#ifndef HEADER_H
#define HEADER_H
class MyClass {};
#endif
Now, if we include it twice, we get this:
#ifndef HEADER_H
#define HEADER_H
class MyClass {};
#endif
#ifndef HEADER_H
#define HEADER_H
class MyClass {};
#endif
And this is what happens when the preprocessor processes it:
#ifndef HEADER_H // HEADER_H is not defined, so we enter the "if" block
#define HEADER_H // HEADER_H is now defined
class MyClass {};// MyClass is now defined
#endif // leaving the "if" block
#ifndef HEADER_H // HEADER_H *is* defined, so we do *not* enter the "if" block
//#define HEADER_H
//
//class MyClass {};
//
#endif // end of the skipped "if" block
So, the end result is that MyClass got defined only once, even though the header was included twice. And so the resulting code is valid.
This is an important property of header files. Always define your headers so that it is valid to include them multiple times.
It depends on the header file; there is no language restriction on multiple includes of the same file.
Some files are designed to be included multiple times (e.g. <assert.h> can be included multiple times to turn 'on' and 'off' assert).
Many files are safe to be included multiple times because they have include guards, others are not and should be included only once in a translation unit or even a program.
include has nothing to do with the C or C++ language. It is a directive to the preprocessor to bring in a file. The preprocessor doesn't care what file is brought in and it shouldn't. It might be perfectly acceptable to do this:
void Foo::SomeFunc(int cond)
{
switch (cond) {
case kThisCase:
#include "longFirstCase.h"
break;
case kSecondCase:
#include "longSecondCase.h"
break;
case kThirdCase:
#include "longFirstCase.h"
#include "longSecondCase.h"
break;
}
}
I have seen the same file included several times as a configuration mechanism as well.
Granted, there are a number of ways to factor that example that are better, but the point is that there may be perfectly good reasons why you would want to and therefore no restriction on the use.
Probably you have some #define in DLLDefines.h around your code that prevents it from being included twice.
#ifndef DLLDEFINES_H
#define DLLDEFINES_H
// your code
#endif
As long as the multiple inclusion of header files do not violate ODR (One definition Rule) $3.2, the code is well-formed.
It's called an include guard.
#ifndef GRANDFATHER_H
#define GRANDFATHER_H
struct foo {
int member;
};
#endif
Quote from Wikipedia:
In the C and C++ programming languages, an #include guard, sometimes called a macro guard, is a particular construct used to avoid the problem of double inclusion when dealing with the #include directive. The addition of #include guards to a header file is one way to make that file idempotent.
See link above for more information.
DLLDefines.h may also have #pragma once at the
top, #pragma once ensures that file gets included only once.