Can a #define or similar pre-processor definition be made across all translation units?
Header implementations are useful for really small libraries since all the code can be contained and distributed with a single header with the following structure:
// library.h
void libFunc(); // forward decl
#ifdef IMPLEMENT_LIBRARY
int libState;
volatile int libVolState; // library state exposed to external processes
void libFunc(){
// definition
}
#endif
This structure however requires the user to define IMPLEMENT_LIBRARY before the header's inclusion in only one of their translation units, meaning it can't be put in the user's header files, and might be a little confusing to someone who isn't wholely familiar with C++'s compilation rules.
If there were a way to define IMPLEMENT_LIBRARY across all TU, this could be done automatically with
#ifndef IMPLEMENT_LIBRARY
#defineToAllUnits IMPLEMENT_LIBRARY
// library state
// definitions
#endif
Does such a mechanism exist, or is the current single-header system as good as it's gonna get?
Some compilation units could very well have been compiled before the one which would contain a #defineToAllUnits, so that is not possible.
In practice your problem is often solved by using the build system to pass a -DIMPLEMENTAT_LIBRARY option to compiler (or equivalent syntax). Another possibility, common when trying to achieve a wide portability with several defines, is to have a configuration header like config.h included everywhere. That header can be autogenerated at configuration time.
You can also avoid infringing the ODR by using inline functions and variables.
For this use case, you probably should not use macro definition at all. If you want the function to be defined in the TU of library user, you can use an inline function. Inline functions may be defined in more than one TU (as long as the definition is same):
// library.h
inline void libFunc(){
// definition
}
Another approach would be to compile the library separately, and have the user of the library link with it instead of having the definition inside their own TU.
Regarding the question itself
Can a #define or similar pre-processor definition be made across all translation units?
It is OK to #define pre-processor macros in more than one TU:
// a.cpp
#define foo a
// b.cpp
#define foo b
If you want the definitions to match across all TU that define it, you can put the macro definition into a header file, and include that:
// h.hpp
#define foo h
// a.cpp
#include "h.hpp"
// b.cpp
#include "h.hpp"
It is not possible to "inject" definitions from one TU into other TU's, so there is no possible equivalent of "#defineToAllUnits". It is typically possible to "inject" macro definitions from the compiler invocation: gcc a.cpp b.cpp -Dfoo=h. I don't see this being useful for your use case however.
Related
I have a c++ header file containing a class.
I want to use this class in several projects, bu I don't want to create a separate library for it, so I'm putting both methods declarations and definitions in the header file:
// example.h
#ifndef EXAMPLE_H_
#define EXAMPLE_H_
namespace test_ns{
class TestClass{
public:
void testMethod();
};
void TestClass::testMethod(){
// some code here...
}
} // end namespace test_ns
#endif
If inside the same project I include this header from more than one cpp file, I get an error saying "multiple definition of test_ns::TestClass::testMethod()", while if I put the method definition inside the class body this does not happen:
// example.h
#ifndef EXAMPLE_H_
#define EXAMPLE_H_
namespace test_ns{
class TestClass{
public:
void testMethod(){
// some code here...
}
};
} // end namespace test_ns
#endif
Since the class is defined inside a namespace, shouldn't the two forms be equivalent? Why is the method considered to be defined twice in the first case?
Inside the class body is considered to be inline by the compiler.
If you implement outside of body, but still in header, you have to mark the method as 'inline' explicitly.
namespace test_ns{
class TestClass{
public:
inline void testMethod();
};
void TestClass::testMethod(){
// some code here...
}
} // end namespace test_ns
Edit
For myself it often helps to solve these kinds of compile problems by realizing that the compiler does not see anything like a header file. Header files are preprocessed and the compiler just sees one huge file containing every line from every (recursively) included file. Normally the starting point for these recursive includes is a cpp source file that is being compiled.
In our company, even a modest looking cpp file can be presented to the compiler as a 300000 line monster.
So when a method, that is not declared inline, is implemented in a header file, the compiler could end up seeing void TestClass::testMethod() {...} dozens of times in the preprocessed file. Now you can see that this does not make sense, same effect as you'd get when copy/pasting it multiple times in one source file.
And even if you succeeded by only having it once in every compilation unit, by some form of conditional compilation ( e.g. using inclusion brackets ) the linker would still find this method's symbol to be in multiple compiled units ( object files ).
These are not equivalent. The second example given has an implicit 'inline' modifier on the method and so the compiler will reconcile multiple definitions itself (most likely with internal linkage of the method if it isn't inlineable).
The first example isn't inline and so if this header is included in multiple translation units then you will have multiple definitions and linker errors.
Also, headers should really always be guarded to prevent multiple definition errors in the same translation unit. That should convert your header to:
#ifndef EXAMPLE_H
#define EXAMPLE_H
//define your class here
#endif
Don't put a function/method definition in an header file unless they are inlined (by defining them directly in a class declaration or explicity specified by the inline keyword)
header files are (mostly) for declaration (whatever you need to declare). Definitions allowed are the ones for constants and inlined functions/methods (and templates too).
Actually it is possible to have definitions in a single header file (without a separate .c/.cpp file) and still be able to use it from multiple source files.
Consider this foobar.h header:
#ifndef FOOBAR_H
#define FOOBAR_H
/* write declarations normally */
void foo();
void bar();
/* use conditional compilation to disable definitions when necessary */
#ifndef ONLY_DECLARATIONS
void foo() {
/* your code goes here */
}
void bar() {
/* your code goes here */
}
#endif /* ONLY_DECLARATIONS */
#endif /* FOOBAR_H */
If you use this header in only one source file, include and use it normally.
Like in main.c:
#include "foobar.h"
int main(int argc, char *argv[]) {
foo();
}
If there're other source files in your project which require foobar.h, then #define ONLY_DECLARATIONS macro before including it.
In use_bar.c you may write:
#define ONLY_DECLARATIONS
#include "foobar.h"
void use_bar() {
bar();
}
After compilation use_bar.o and main.o can be linked together without errors, because only one of them (main.o) will have implementation of foo() and bar().
That's slightly non-idiomatic, but it allows to keep definitions and declarations together in one file. I feel like it's a poor man's substitute for true modules.
Your first code snippet is falling foul of C++'s "One Definition Rule" - see here for a link to a Wikipedia article describing ODR. You're actually falling foul of point #2 because every time the compiler includes the header file into a source file, you run into the risk of the compiler generating a globally visible definition of test_ns::TestClass::testMethod(). And of course by the time you get to link the code, the linker will have kittens because it will find the same symbol in multiple object files.
The second snippet works because you've inlined the definition of the function, which means that even if the compiler doesn't generate any inline code for the function (say, you've got inlining turned off or the compiler decides the function is too big to inline), the code generated for the function definition will be visible in the translation unit only, as if you'd stuck it in an anonymous namespace. Hence you get multiple copies of the function in the generated object code that the linker may or may not optimize away depending on how smart it is.
You could achieve a similar effect in your first code snippet by prefixing TestClass::testMethod() with inline.
//Baseclass.h or .cpp
#ifndef CDerivedclass
#include "Derivedclass.h"
#endif
or
//COthercls.h or .cpp
#ifndef CCommonheadercls
#include "Commonheadercls.h"
#endif
I think this suffice all instances.
I am looking for a way to reduce compile-time for header-only libraries. If there are only headers, each translation unit must compile all functions it needs, hence there is a lot of duplicate work done in the compilation step. My idea is to move the compilation to a single translation unit, which creates a single object file the other translation units can link to. This allows the header-only library to effectively behave like a static library which is compiled along with the actual productive code.
A typical header of the library looks like this. It includes all the declarations (all inline of course), while the definitions are hidden behind the macro MYUTILS_INLINE.
// MyUtils1.hpp, example utility header
#ifndef MyUtils1_h__
#define MyUtils1_h__
class MyClass1{...};
inline int myfunction1(void);
#ifdef MYUTILS_INLINE
#include MyUtils1.cpp
#endif // MYUTILS_INLINE
#endif // MyUtils1_h__
MyUtils1.cpp can include additional headers required for the implementation and contains the definitions.
// MyUtils1.cpp, example implementation file
#include MyUtils1.hpp
#include "additionalheader.hpp"
MyClass1::MyClass1(void) {...}
inline int myfunction1(void){...}
In my code, the headers of the library can be included normally. There is one additional file MyUtils.cpp or MyUtils.inl, which is the only file which sets MYUTILS_INLINE and hence sees the definitions and compiles them:
// MyUtils.cpp, separate translation unit in my project
// set macro to get the definitions and compile them.
#define MYUTILS_INLINE
// include all headers which are used throughout the project
#include "MyUtils1.hpp"
#include "MyUtils2.hpp"
#include "MyUtils3.hpp"
Advantages:
reduced compile-time due to no duplicate work
fewer header dependencies, headers needed for definitions can be hidden in MyUtils1.cpp
opt-in behavior: If user defines MYUTILS_INLINE globally, he does not need MyUtils.cpp and all works as before
Disadvantages:
less optimization potential because functions are no longer inline
ship twice as many files (one implementation file for each header)
Now before I restructure my entire library, I want to ask for thoughts about this:
Did I just reinvent something?
Do I miss some important points? Advantages or disadvantages?
Is there a similar or better way?
I noticed that Catch actually does something similar with CATCH_CONFIG_MAIN.
EDIT
I have read some articles about precompiled headers and tried them in one of my projects. While they try to solve the same problem, they have other issues, especially regarding clean dependencies between header files. My suggested approach is considerably different, as each file still manages its own dependencies but has the option to pass work to the translation unit MyUtils.cpp.
I have a project with multiple header files and .cpp files.
All of the header files have include guards.
There is a file called Constants.h where I define some constants. Some of these with defines, some as constant variables.
There are more header-.cpp-file pairs with code in them. One of these does contain a class, the others don't.
When I include my files into my main file (an arduino sketch), I get a lot of linker errors, claiming there are multiple definitions of some variables.
I read that this mainly occurs when you include .c or .cpp files, which I don't do. All the .cpp files only include their appropriate header files.
I did manage to find multiple solution proposals:
1) inline:
With functions, inline can be used to get rid of this problem. However, this is not possible with variables.
2) anonymous namespace:
This is one of the solutions I used. I put anonymous namespaces around all the problematic definitions I had. It did work, however I do not understand why this works. Could anyone help me understand it?
3) moving definitions into .cpp files:
This is another approach I used sometimes, but it wasn't always possible since I needed some of my definitions in other code, not belonging to this header file or its code (which I do admit is bad design).
Could anyone explain to me where exactly the problem lies and why these approaches work?
Some of these with defines, some as constant variables.
In C const does not imply the same thing as it does in C++. If you have this:
const int foo = 3;
In a header, then any C++ translation unit that includes the header will have a static variable named foo (the const at namespace scope implies internal linkage). Moreover, foo can even be considered a constant expression by many C++ constructs.
Such is not the case in C. There foo is an object at file scope with external linkage. So you will have multiple definitions from C translation units.
A quick fix would be to alter the definitions into something like this:
static const int foo = 3;
This is redundant in C++ but required in C.
In addition to Story Teller's excellent explanation, to define global variables, use the following:
// module.h
#include "glo.h"
// glo.h
#ifndef EXTERN
# define EXTERN extern
#endif
EXTERN int myvar;
// main.c
#define EXTERN
#include "glo.h"
In main.c all variables will be declared (i.e. space is allocated for them), in all other c files that include glo.h, all variables will be known.
You shouldn't declare any object in header files, this should be moved to c\c++ files.
In header you may:
declare types such as: classes, structs, typedefs etc.
put forward declarations of (not classes) functions
put inline (or in classes) functions (+ body)
you may add extern declaration.
you may put your macros.
a static declaration may declare things multiple times, therefore it is not recommended.
Is there any difference between inline member function (function body inline) and other normal member function (function body in a separate .cpp file)?
for example,
class A
{
void member(){}
};
and
// Header file (.hpp)
class B
{
void member();
};
// Implementation file (.cpp)
void B::member(){}
There is absolutely no difference.
The only difference between the two is that the member inside the class is implicitly tagged as inline. But this has no real meaning.
See: inline and good practices
The documentation says that the inline tag is a hint to the compiler (by the developer) that a method should be inlined. All modern compilers ignore this hint and use there own internal heuristic to determine when a method should be inlined (As humans are notoriously bad and making this decision).
The other use of inline is that it tells the linker that it may expect to see multiple definitions of a method. When the function definition is in the header file each compilation unit that gets the header file will have a definition of the function (assuming it is not inlined). Normally this would cause the linker to generate errors. With the inline tag the compiler understands why there are multiple definitions and will remove all but one from the application.
Note on inlining the processes: A method does not need to be in the header file to inlined. Modern compilers have a processes a full application optimization where all functions can be considered for inlining even if they have been compiled in different compilation units. Since the inline flag is generally ignored it make no difference if you put the method in the header or the source file.
Ignore the word inline here and compiler hints because it is not relevant.
The big practical difference in A and B is when they are used in different libraries.
With the case of A you can #include the header and are not required to link against anything. So you can use this class from different applications / libraries without any special linkage.
With the case of B, you need B.cpp and this should be compiled only into one library / application. Any other library or application that needs to use this class will need to link against the one that contains the actual body of the code.
With some setups / implementations you will need to specifically mark the class as "exported" or "imported" between libraries (for example with Windows you can use dllimport / dllexport and with GNU you can use attribute(visibility="default") )
The first one is implicitly inline, i.e. suggesting the compiler to expand it at the call site.
Other than the inline thing, there's a difference in that you could put more definitions in between the definition of class B, and the definition of the function.
For example, B.cpp might include header files that B.hpp doesn't, which can make a significant difference to the build process for large projects.
But even without a separate translation unit, you can occasionally have a circular dependency that's resolved by separating the definitions. For example the function might take a parameter of a type that's forward-declared before B is defined, then defined by the time the function is defined. If that type uses the definition of B in its own definition, it can't just be be defined before B.
I am new to C++ and I had a few general questions about code separation. I have currently built a small application, all in one file. What I want to do now is convert this into separate files such that they contain similar code or whatnot. My real question right now is, how do I know how to separate things? What is the invisible margin that code should be separated at?
Also, what's the point of header files? Is it to forward declare methods and classes so I can use them in my code before they are included by the linker during compilation?
Any insight into methods or best practises would be great, thanks!
Header files should contain class and function declarations.
Source files contain class and function definitions.
It is standard practice (i.e. read easier) to have one declaration per header file and one definition per source file, though for small (read simpler helper) objects you sometimes group them with related more substantial objects.
Example: Class Menu
Menu.h: Contains the Menu declaration.
Menu.cpp: Contains the Menu definition.
The reason header files contain the declarations is so that you can include them from multiple source files and thus each source file has exactly the same definition of each class and function.
Consider it this way:
If you did not have header files then you would need to have the class and/or function declarations (without) definitions in every source file, this means a copy of the same declaration in every file. Thus if you modify a class you need to make the same modification in every file. By the use of a header file you have the declaration in one place and thus only one object to modify.
First, you should not put anything into headers that is not needed to be visible by any other file, other than the one that needs it. Then, let's define something we need below.
Translation Unit
A Translation Unit is the current code being compiled, and all the code included
by it, directly or indirectly. One Translation unit translates to one .o / .obj file.
Program
That's all your .o / .obj files linked together into one binary file that can be
executed to form a process.
What are the main points of having different translation units?
Reduce dependencies, so that if you change one method of one class, you don't have to recompile all the code of your program, but only the affected translation unit. An
Reduce possible name clashes by having translation unit local names, that are not visible by other translation unit when linking them together.
Now, how can you split your code into different translation units? The answer is there is no "so you do it!", but you have to consider it on a case-by-case basis. It's often clear, since you have different classes, which can and should be put in different translation units:
foo.hpp:
/* Only declaration of class foo we define below. Note that a declaration
* is not a definition. But a definition is always also a declaration */
class foo;
/* definition of a class foo. the same class definition can appear
in multiple translation units provided that each definition is the same
basicially, but only once per translation unit. This too is called the
"One Definition Rule" (ODR). */
class foo {
/* declaration of a member function doit */
void doit();
/* definition of an data-member age */
int age;
};
Declare some free functions and objects:
/* if you have translation unit non-local (with so-called extern linkage)
names, you declare them here, so other translation units can include
your file "foo.hpp" and use them. */
void getTheAnswer();
/* to avoid that the following is a definition of a object, you put "extern"
in front of it. */
extern int answerCheat;
foo.cpp:
/* include the header of it */
#include "foo.hpp"
/* definition of the member function doit */
void foo::doit() {
/* ... */
}
/* definition of a translation unit local name. preferred way in c++. */
namespace {
void help() {
/* ... */
}
}
void getTheAnswer() {
/* let's call our helper function */
help();
/* ... */
}
/* define answerCheat. non-const objects are translation unit nonlocal
by default */
int answerCheat = 42;
bar.hpp:
/* so, this is the same as above, just with other classes/files... */
class bar {
public:
bar(); /* constructor */
};
bar.cpp:
/* we need the foo.hpp file, which declares getTheAnswer() */
#include "foo.hpp"
#include "bar.hpp"
bar::bar() {
/* make use of getTheAnswer() */
getTheAnswer();
}
Please note that names within an anonymous namespace (as above) do not clash since they appear to be translation unit local. in reality they are not, they just have unique names so that they do not clash. if you really want (there is little reason to) translation unit local names (for example because of compatibility with c so C code can call your function) you can do it like this:
static void help() {
/* .... */
}
The ODR also says that you cannot have more than one definition of any object or non-inline function in one program (classes are types, not objects, so it doesn't apply to them). So you have to watch out not to put non-inline functions into headers, or not putting objects like "int foo;" in headers. That will cause linker errors then when the linker tries to link the translation units including those headers together.
I hope i could help you a bit. Now that was a long answer, there are indeed errors somewhere. I know that a translation unit strictly is defined another way (output of the pre-processor). But i think it would not add big value to include that into the above, and it would confuse the matter. Please feel free to slap me if you find real bugs :)
Deciding how to separate your code into different classes/functions is one of main tasks of programing. There are many different guidelines on how to do this and I would recommend reading some tutorials on C++ and Object Oriented Design to get you started.
Some basic guidelines will be
Put things together which are used
together
Create classes for domain objects
(eg files, collections etc)
Header files allow you to declare a class or function and then use it in several different source files. For example, if you declare a class in a header file
// A.h
class A
{
public:
int fn();
};
You can then use this class in several source files:
// A.cpp
#include "A.h"
int A::fn() {/* implementation of fn */}
//B.cpp
#include "A.h"
void OtherFunction() {
A a;
a.fn();
}
So header files enable you to separate the declaration from the implementation. If you were to put everything (declaration and implementation) in a source file (eg A.cpp) then try to include that in a second file, eg
// B.cpp
#include "A.cpp" //DON'T do this!
Then you could compile B.cpp but when you try to link your program the linker will complain that you have multiply defined objects - this is because you have multiple copies of the implementation of A.
Suggestion:
1. Have a design ready for your application now.
2. Based on the design, create necessary objects that interact with each other.
3. Refactor or completely change the existing code to suit the newly created design.
Header files provide an interface to the other classes that might use it's functionality.