For some reason, it seems that C++ doesn't like it when you split a template class (i.e. a class declared as template <typename T> class Thing) into a .h and a .cpp file, like you would do with any other class.
Does that mean that when writing a template class, I should just write it all in the header file? What do C++ programmers do in these cases?
EDIT: I understand that there are alternatives to writing it all in the .h file. But what's the best option? Or what the most common option?
It is popular to split the definition of a template out into another file. It is so popular it may even be the most common practice, but I am not positive about that.
I think this is poor practice (as opposed to putting the definitions in the same header) for the following reasons.
My priorities when writing code are (most important first):
Correctness.
Run time performance.
Compile time performance.
Maintainability / Easy to read.
Easy to write.
As long as the template definition is in the same header, or in another file that the header includes, the number one priority Correctness is not impacted one way or the other.
The second priority Run time performance is not impacted in the least.
The third priority Compile time performance is negatively impacted by putting the definition in a separate file. By how much is debatable. But there is no way that a compiler can compile X amount of code and open/close two files, as fast as it can compile the exact same code while opening/closing only one file. A friend of mine who is an excellent compiler writer once told me that the slowest thing I could ask his compiler to do was to open a file. This was before we did as much compile-time computation as we do today, but still...
The fourth priority Maintainability / Easy to read is quite subjective. But in my opinion a separate file is a negative impact on this priority. When I'm reading code, it is typically easier for me to understand it if it is all in one file. And I really get annoyed when I have to go hunting for the file when its name or location is not obvious. And I get even more annoyed when the definition is split into many files. For my money, one file optimizes this priority.
The fifth priority Easy to write is also quite subjective. I don't see much advantage either way on this one. It is very slightly easier to put everything in one file. But it is certainly not difficult to create a new file. I give the "one file approach" a very slight advantage on this priority.
So in summary, out of my five priorities, the two most important, this decision makes absolutely no difference on, and separate files have small negative consequences for the 3 lower priorities. Of the 3 lower priorities, the most important of these, compile-time performance is objectively negatively impacted. The two lowest priorities are admittedly subjective as to whether or not they are positively or negatively impacted.
I see no benefit and a small cost to putting your template definitions in a separate header.
"Does that mean that when writing a template class, I should just write it all in the header file? What do C++ programmers do in these cases?"
What you can do (and is wide spread/popular practice), is separate implementation code out to special template implementation files, that will in turn be in íncluded by the template headers, containing the declarations.
The gain of this technique is considered little for most of the cases, though it has it's points, if you want to hide the implementation details and not spill header files to become large.
The point is not to have the template definition code, or specializations in separate translation units, such these can be seen directly by other translation units, including the template header file.
The common pattern is
MyTemplate.h
#if !defined(MYTEMPLATE_H_)
#define MYTEMPLATE_H_
namespace myspace {
template <typename T>
class MyTemplate {
public:
void foo(T value);
};
#include "MyTemplate.tcc"
}
#endif // MYTEMPLATE_H_
MyTemplate.tcc
// NOTE: There aren't header guards for this file intentionally!
template<typename T>
void MyTemplate<T>::foo(T value) {
// ...
}
Other popular extensions for template implementation files are .icc, .ipp, .impl. Just important, it shouldn't be .cpp, since most IDE's or build system frameworks will track this as translation unit, unless it's explicitly excluded (here's a sample why).
"So simply instead of the .cpp #includeing the header, the header #includes the .tpp (which contains the implementations)?"
Template classes work a bit differently regarding the ODR (one definition rule). Regular header files, that provide class declarations shouldn't contain implementations because the ODR would be violated when these are included from different translation units:
MyClass.h
class MyClass {
public:
void foo(int);
};
// Violates ODR if MyClass.h is included from different translation units (.cpp files)
void MyClass::foo(int param) {
}
The templated version
template<typename T>
class MyClass {
public:
void foo(T);
};
// Doesn't violate ODR if MyClass.h is included from different translation units
// (.cpp files), since the template parameter isn't instatiated here yet.
template<typename T>
void MyClass<T>::foo(T param) {
}
As soon one translation unit instantiated something like MyClass<int>, other translation units instatiating the same template signature, will use the 1st one seen.
The latter implementation part could be replaced with an #include "MyClass.impl" that contains that code, if you think it messes up readability or maintainability of your header file too much.
As a minor drawback of the #include "MyClass.tcc" technique, you should notice, that most of the popular IDE's handle syntax highlighting and intellisense poorly for these kind of template implementation files.
Related
I have been told by some colleagues (who are smart than me) that moving implementation (definition) outside header can reduce compile time in some cases - I should do it in most case.
After a lot of refactoring, I believe it is true.
Now I plan to move implementation of very simple functions too. (.h -> .cpp)
void f(int index){
return database[index*2]; //<--- contain trivial algorithm like this
}
Question
What are the factors to determine how much the benefit?
More specifically :-
Does the amount of time used to compile saved depends on
amount of characters (exclude comment) I moved to .cpp or ...
complexity (not mean O(n) here) of algorithm of function or ...
something else ?
Should I move definition of such simple functions to .cpp?
(concern only performance and compile time, not concern maintainability or readability)
Edit: detailed example
Consider this code.
B.h :-
class B{
public: static void fb(){
//some complex code (e.g. 1000 lines)
}
};
C.h :-
#include "B.h"
class C{
static void fc();
};
C.cpp contains implementation of fc()
D.h :-
#include "B.h"
class D{
static void fd();
};
D.cpp contains implementation of fd()
Before moving definition of fb, the compiler will have to compile large code of B.h for C.cpp and D.cpp.
After moving definition of fb to b.cpp, I think C.cpp and D.cpp will be a lot easier to compile.
What are the factors to determine how much the benefit?
The major factor for reduction of compile time depends on how many other translation units include that header with the inlined code. The other factors you mentioned are merely irrelevant.
If you change something in the definition many more files would need to be recompiled, than if you change the definition only in a single .cpp file.
Should I move definition of such simple functions to .cpp?
(concern only performance and compile time, not concern maintainability or readability)
No, what I said above refers to non trivial stuff. If you have such simple function definition and it's unlikely it will be changed in future, you can leave it in the header file.
The answer can be simple and less simple.
Simple answer:
put implementation of non-trivial function in the source files, there are many advantages to this, not just compilation time.
Leave implementation of trivial function in the header file and make non-member-functions inline, the compilation time will not differ significantly and there are even better optimization possibilities.
Less simple:
Putting non-trivial functions in source file is done specifically so the header files, which are like interfaces to the code, are more readable, don't have to contain all the includes needed for implementation, can prevent mutual cycle issues and on top have better compilation times.
Putting trivial functions in the header file let the compiler do better optimisation during compile-time (as opposed to link-time) because it knows at the calling point what the function does, so it knows better when to inline and reorder code (see here for link-time optimization).
Templates should still always be in header files. for some complex functions, the non-template part may be factored out and put in a source file, but this can be fiddly.
For encapsulation reasons, it may be better to declare helper functions and helper classes in the source file completely.
When using pimpl-constructs, the trivial delegation functions, must be in the source file because only there, the pimpl is fully known.
So in the end ordering the code can cause better compilation times, but that shouldn't be the main reason.
If you call this function which's body is in .h , it will get reference to your #include's in order to find it, because #include gives only a reference.
It will be easier for the compiler if your function's body is in .cpp
I suggest you check this out. It helped me too.
What techniques can be used to speed up C++ compilation times?
Why is it a bad practice to define the functions of the class in the header files?
Lets say I have a header file and I define the functions of the class in the class definition itself like,
headerfile.hpp
#ifndef _HEADER_FILE_
#define _HEADER_FILE_
class node{
int i;
public:
int nextn(){
......
return i;
}
}
#endif //_HEADER_FILE_
So defining the function in the class like this makes the function "Inline".So if we include this header file in say two .cpp files, will it cause "Multiple definition error" ??Is it a bad practice to define the functions like this in the class definition?
It is a bad practice for the following reasons: If you need to change the code, let's say to add a trace in a simple setter (they are commonly in the .h); then you will need to recompile all CPP files that #includes the change (and any dependency of). In my current project that could reach up to 1 hour lost. If you later need to add another trace, then another and so on you quickly loose 1-2 days or work waiting for the compiler.
If you place your code in the CPP, then you only need to re-link, and that takes only a few minutes. Your project may be small today, but who knows in a few years. It's just a good habit to take.
Another (not so good) reason is that if you search your code base for the string "::MyFonction" you will not find it in the declaration since there is no "::" (we only want implementations). But a good IDE should find it anyway using a context search instead of a string search.
It's not bad practise (in fact it's commonplace) and it will not cause multiple definition errors. Inline functions never cause multiple definition errors, that's one of the meanings of inline.
The convention to separate prototypes (that is, the declaration of the class, its functions, their types) from implementation comes from both a design and a performance point of view.
Type checking and compiling your dependants is cheaper. Something that uses your class can be safely compiled without knowing your implementation.
Your compiler won't need to parse and recompile the same information lots of times each time you do compile those dependants.
The thing is to remember what it really means with you write #include at the top of a file in C++: it means "take all the contents of some other file, and put them here." So if you're using a class in lots of places all over your code base, then it's getting parsed every single time, and re-compiled in the context of that compilation unit.
This is precisely the reason why you have to put implementations of template classes in-line in the header file; the compiler needs to re-parse and compile the class for every different template instantiation (because that's what templates are about).
To answer your question directly:
* No, you will not get a multiple definition error.
* Maybe, some people would consider it back practice from a design points of view (others wouldn't)
* You might see a difference in performance (though not necessarily a degredation, as I believe - though I could be wrong), that despite the above, it can still be faster to compile header-only libraries.
Probably avoid doing this if your implementations are long, the class is used often in the codebase, and will be subject to frequent change.
For further reading, it might be worth checking up on "precompiled headers."
It is legal to define (inline) functions in your hpp file. Note that some people prefer to gather then under a dedicated extension like "inl.hpp", but this is just a style preference.
Thinking Time - Why do you want to split your file anyway?
As the title suggests, the end problem I have is multiple definition linker errors. I have actually fixed the problem, but I haven't fixed the problem in the correct way. Before starting I want to discuss the reasons for splitting a class file into multiple files. I have tried to put all the possible scenarios here - if I missed any, please remind me and I can make changes. Hopefully the following are correct:
Reason 1 To save space:
You have a file containing the declaration of a class with all class members. You place #include guards around this file (or #pragma once) to ensure no conflicts arise if you #include the file in two different header files which are then included in a source file. You compile a separate source file with the implementation of any methods declared in this class, as it offloads many lines of code from your source file, which cleans things up a bit and introduces some order to your program.
Example: As you can see, the below example could be improved by splitting the implementation of the class methods into a different file. (A .cpp file)
// my_class.hpp
#pragma once
class my_class
{
public:
void my_function()
{
// LOTS OF CODE
// CONFUSING TO DEBUG
// LOTS OF CODE
// DISORGANIZED AND DISTRACTING
// LOTS OF CODE
// LOOKS HORRIBLE
// LOTS OF CODE
// VERY MESSY
// LOTS OF CODE
}
// MANY OTHER METHODS
// MEANS VERY LARGE FILE WITH LOTS OF LINES OF CODE
}
Reason 2 To prevent multiple definition linker errors:
Perhaps this is the main reason why you would split implementation from declaration. In the above example, you could move the method body to outside the class. This would make it look much cleaner and structured. However, according to this question, the above example has implicit inline specifiers. Moving the implementation from within the class to outside the class, as in the example below, will cause you linker errors, and so you would either inline everything, or move the function definitions to a .cpp file.
Example: _The example below will cause "multiple definition linker errors" if you do not move the function definition to a .cpp file or specify the function as inline.
// my_class.hpp
void my_class::my_function()
{
// ERROR! MULTIPLE DEFINITION OF my_class::my_function
// This error only occurs if you #include the file containing this code
// in two or more separate source (compiled, .cpp) files.
}
To fix the problem:
//my_class.cpp
void my_class::my_function()
{
// Now in a .cpp file, so no multiple definition error
}
Or:
// my_class.hpp
inline void my_class::my_function()
{
// Specified function as inline, so okay - note: back in header file!
// The very first example has an implicit `inline` specifier
}
Reason 3 You want to save space, again, but this time you are working with a template class:
If we are working with template classes, then we cannot move the implementation to a source file (.cpp file). That's not currently allowed by (I assume) either the standard or by current compilers. Unlike the first example of Reason 2, above, we are allowed to place the implementation in the header file. According to this question the reason is that template class methods also have implied inline specifiers. Is that correct? (It seems to make sense.) But nobody seemed to know on the question I have just referenced!
So, are the two examples below identical?
// some_header_file.hpp
#pragma once
// template class declaration goes here
class some_class
{
// Some code
};
// Example 1: NO INLINE SPECIFIER
template<typename T>
void some_class::class_method()
{
// Some code
}
// Example 2: INLINE specifier used
template<typename T>
inline void some_class::class_method()
{
// Some code
}
If you have a template class header file, which is becoming huge due to all the functions you have, then I believe you are allowed to move the function definitions to another header file (usually a .tpp file?) and then #include file.tpp at the end of your header file containing the class declaration. You must NOT include this file anywhere else, however, hence the .tpp rather than .hpp.
I assume you could also do this with the inline methods of a regular class? Is that allowed also?
Question Time
So I have made some statements above, most of which relate to the structuring of source files. I think everything I said was correct, because I did some basic research and "found out some stuff", but this is a question and so I don't know for sure.
What this boils down to, is how you would organize code within files. I think I have figured out a structure which will always work.
Here is what I have come up with. (This is my class code file organization/structure standard, if you like. Don't know if it will be very useful yet, that's the point of asking.)
1: Declare the class (template or otherwise) in a .hpp file, including all methods, friend functions and data.
2: At the bottom of the .hpp file, #include a .tpp file containing the implementation of any inline methods. Create the .tpp file and ensure all methods are specified to be inline.
3: All other members (non-inline functions, friend functions and static data) should be defined in a .cpp file, which #includes the .hpp file at the top to prevent errors like "class ABC has not been declared". Since everything in this file will have external linkage, the program will link correctly.
Do standards like this exist in industry? Will the standard I came up with work in all cases?
Your three points sound about right. That's the standard way to do things (although I've not seen .tpp extension before, usually it's .inl), although personally I just put inline functions at the bottom of header files rather than in a separate file.
Here is how I arrange my files. I omit the forward declare file for simple classes.
myclass-fwd.h
#pragma once
namespace NS
{
class MyClass;
}
myclass.h
#pragma once
#include "headers-needed-by-header"
#include "myclass-fwd.h"
namespace NS
{
class MyClass
{
..
};
}
myclass.cpp
#include "headers-needed-by-source"
#include "myclass.h"
namespace
{
void LocalFunc();
}
NS::MyClass::...
Replace pragma with header guards according to preference..
The reason for this approach is to reduce header dependencies, which slow down compile times in large projects. If you didn't know, you can forward declare a class to use as a pointer or reference. The full declaration is only needed when you construct, create or use members of the class.
This means another class which uses the class (takes parameters by pointer/reference) only has to include the fwd header in its own header. The full header is then included in the second class's source file. This greatly reduces the amount of unneeded rubbish you get when pulling in a big header, which pulls in another big header, which pulls in another...
The next tip is the unnamed namespace (sometimes called anonymous namespace). This can only appear in a source file and it is like a hidden namespace only visible to that file. You can place local functions, classes etc here which are only used by the the source file. This prevents name clashes if you create something with the same name in two different files. (Two local function F for example, may give linker errors).
The main reason to separate interface from implementation is so that you don't have to recompile all of your code when something in the implementation changes; you only have to recompile the source files that changed.
As for "Declare the class (template or otherwise)", a template is not a class. A template is a pattern for creating classes. More important, though, you define a class or a template in a header. The class definition includes declarations of its member functions, and non-inine member functions are defined in one or more source files. Inline member functions and all template functions should be defined in the header, by whatever combination of direct definitions and #include directives you prefer.
Do standards like this exist in industry?
Yes. Then again, coding standards that are rather different from the ones you expressed can also be found in industry. You are talking about coding standards, after all, and coding standards range from good to bad to ugly.
Will the standard I came up with work in all cases?
Absolutely not. For example,
template <typename T> class Foo {
public:
void some_method (T& arg);
...
};
Here, the definition of class template Foo doesn't know a thing about that template parameter T. What if, for some class template, the definitions of the methods vary depending on the template parameters? Your rule #2 just doesn't work here.
Another example: What if the corresponding source file is huge, a thousand lines long or longer? At times it makes sense to provide the implementation in multiple source files. Some standards go to the extreme of dictating one function per file (personal opinion: Yech!).
At the other extreme of a thousand-plus line long source file is a class that has no source files. The entire implementation is in the header. There's a lot to be said for header-only implementations. If nothing else, it simplifies, sometimes significantly, the linking problem.
It used to be that to use a template class in C++, the implementations had to be in the header file or #included into the header file at the bottom.
I've not used C++ templates for a few years; I just started using them again and observed that this behavior seems to persist. Is this still the case? Or are the compilers smart enough now to have the implementation separate from the interface?
Technically they do not need to be in the header file.
An example of this usage is when you have a template class with a fixed set of versions (lets say for arguments sake char and wchar_t). Then you can put all the method delcarations into a source file and explicitly instanciate these two versions. This has the safety that others can not istanciate the template for types it was not meant to be used for.
// X.h
template<typename T>
class X
{
// DECLARATION ONLY OF STUFF
public:
X(T const& t);
private:
T m_t;
};
// X.cpp
#include "X.h"
// DEFINTION OF STUFF
template<typename T>
X<T>::X(T const& t)
:m_t(t)
{}
// INSTANCIATE The versions you want.
template class X<char>;
template class X<wchar_t>;
// Main.cpp
#include "X.h"
int main()
{
X<chat> x1('a');
X<wchar_t> x2(L'A');
// X<int> x3(5); // Uncomment for a linker failure.
}
Assuming people can't just directly include X.cpp (because it is not provided by the distribution) then others can not use X<int> or X<float> etc. But the abovr classes are fully defined.
I have also seen this technique used to reduce compilatio time. Because each compilation unit is not re-generating the same version of X we only get the defintion in one place (thus one compilation cost). The downsize to this is that you must manually instanciate each seprate version of X that you use.
To separate the implementation from the declaration the standard forces you to use the export keyword. As far as I know there's only one compiler that knows how to handle it: Comeau.
However, C++0x will include a mechanism that tells the compiler not to instantiate certain specializations automatically (extern templates). So, if you want to cut compilation time you will be able to do so by explicitly instantiating some specializations in one compilation unit and declaring them in the header as extern.
You are referring to exported templates (using the export keyword), which seem to be supported only by Comeau C++ (according to this section of the C++ FAQ Lite).
A common technique to keep the interface devoid of implementation code is to put the inline function definitions into a separate "implementation" header that can be included at the end of the declaration header.
Export is only support by the EDG frontend, comercially only available in the Comeau compiler as far as I know.
Export doesn't eliminate the need for source disclosure, nor does it reduce compile dependencies, while it requires a massive effort from compiler builders.
So Herb Sutter himself asked compiler builders to 'forget about' export. As the time investment needed would be better spend elsewhere... so I don't think export will ever be implemented by other compilers after they saw how long it took, and how little was gained.
The paper is called "Why we can't afford export", it's listed on Sutters blog but no pdf there (a quick google should turn it up though), it's six years old now, I suppose they all listened and never bothered :)
Many people use two header files (e.g. .hpp and .ipp), one with only the declaration, and one with the definitions, then it's simply a matter of including one in the other.
foo.hpp
#ifndef MY_TEMPLATES_HPP
#define MY_TEMPLATES_HPP
template< class T >
void foo(T & t);
#include "foo.ipp"
#endif
foo.ipp
#ifdef MY_TEMPLATES_IPP
nonsense here, that will generate compiler error
#else
#define MY_TEMPLATES_IPP
template< class T >
void foo(T & t) {
... // long function
}
#endif
This only gains some clarity of course, nothing really changes compared to simply inlining everything in one header file.
GCC goes through a lengthy collect stage unless you explicitly instantiate all templates. VC++ seems to cope, but I prefer to avoid this step anyway and in cases where I know how template is going to be used, which is usually the case for applications, not so much for libraries, I put template definitions into a separate file. This also makes code more readable by making declarations less cluttered with implementation details.
My personal style with C++ has always to put class declarations in an include file, and definitions in a .cpp file, very much like stipulated in Loki's answer to C++ Header Files, Code Separation. Admittedly, part of the reason I like this style probably has to do with all the years I spent coding Modula-2 and Ada, both of which have a similar scheme with specification files and body files.
I have a coworker, much more knowledgeable in C++ than I, who is insisting that all C++ declarations should, where possible, include the definitions right there in the header file. He's not saying this is a valid alternate style, or even a slightly better style, but rather this is the new universally-accepted style that everyone is now using for C++.
I'm not as limber as I used to be, so I'm not really anxious to scrabble up onto this bandwagon of his until I see a few more people up there with him. So how common is this idiom really?
Just to give some structure to the answers: Is it now The Way™, very common, somewhat common, uncommon, or bug-out crazy?
Your coworker is wrong, the common way is and always has been to put code in .cpp files (or whatever extension you like) and declarations in headers.
There is occasionally some merit to putting code in the header, this can allow more clever inlining by the compiler. But at the same time, it can destroy your compile times since all code has to be processed every time it is included by the compiler.
Finally, it is often annoying to have circular object relationships (sometimes desired) when all the code is the headers.
Bottom line, you were right, he is wrong.
EDIT: I have been thinking about your question. There is one case where what he says is true. templates. Many newer "modern" libraries such as boost make heavy use of templates and often are "header only." However, this should only be done when dealing with templates as it is the only way to do it when dealing with them.
EDIT: Some people would like a little more clarification, here's some thoughts on the downsides to writing "header only" code:
If you search around, you will see quite a lot of people trying to find a way to reduce compile times when dealing with boost. For example: How to reduce compilation times with Boost Asio, which is seeing a 14s compile of a single 1K file with boost included. 14s may not seem to be "exploding", but it is certainly a lot longer than typical and can add up quite quickly when dealing with a large project. Header only libraries do affect compile times in a quite measurable way. We just tolerate it because boost is so useful.
Additionally, there are many things which cannot be done in headers only (even boost has libraries you need to link to for certain parts such as threads, filesystem, etc). A Primary example is that you cannot have simple global objects in header only libs (unless you resort to the abomination that is a singleton) as you will run into multiple definition errors. NOTE: C++17's inline variables will make this particular example doable in the future.
As a final point, when using boost as an example of header only code, a huge detail often gets missed.
Boost is library, not user level code. so it doesn't change that often. In user code, if you put everything in headers, every little change will cause you to have to recompile the entire project. That's a monumental waste of time (and is not the case for libraries that don't change from compile to compile). When you split things between header/source and better yet, use forward declarations to reduce includes, you can save hours of recompiling when added up across a day.
The day C++ coders agree on The Way, lambs will lie down with lions, Palestinians will embrace Israelis, and cats and dogs will be allowed to marry.
The separation between .h and .cpp files is mostly arbitrary at this point, a vestige of compiler optimizations long past. To my eye, declarations belong in the header and definitions belong in the implementation file. But, that's just habit, not religion.
Code in headers is generally a bad idea since it forces recompilation of all files that includes the header when you change the actual code rather than the declarations. It will also slow down compilation since you'll need to parse the code in every file that includes the header.
A reason to have code in header files is that it's generally needed for the keyword inline to work properly and when using templates that's being instanced in other cpp files.
What might be informing you coworker is a notion that most C++ code should be templated to allow for maximum usability. And if it's templated, then everything will need to be in a header file, so that client code can see it and instantiate it. If it's good enough for Boost and the STL, it's good enough for us.
I don't agree with this point of view, but it may be where it's coming from.
I think your co-worker is smart and you are also correct.
The useful things I found that putting everything into the headers is that:
No need for writing & sync headers and sources.
The structure is plain and no circular dependencies force the coder to make a "better" structure.
Portable, easy to embedded to a new project.
I do agree with the compiling time problem, but I think we should notice that:
The change of source file are very likely to change the header files which leads to the whole project be recompiled again.
Compiling speed is much faster than before. And if you have a project to be built with a long time and high frequency, it may indicates that your project design has flaws. Seperate the tasks into different projects and module can avoid this problem.
Lastly I just wanna support your co-worker, just in my personal view.
Often I'll put trivial member functions into the header file, to allow them to be inlined. But to put the entire body of code there, just to be consistent with templates? That's plain nuts.
Remember: A foolish consistency is the hobgoblin of little minds.
As Tuomas said, your header should be minimal. To be complete I will expand a bit.
I personally use 4 types of files in my C++ projects:
Public:
Forwarding header: in case of templates etc, this file get the forwarding declarations that will appear in the header.
Header: this file includes the forwarding header, if any, and declare everything that I wish to be public (and defines the classes...)
Private:
Private header: this file is a header reserved for implementation, it includes the header and declares the helper functions / structures (for Pimpl for example or predicates). Skip if unnecessary.
Source file: it includes the private header (or header if no private header) and defines everything (non-template...)
Furthermore, I couple this with another rule: Do not define what you can forward declare. Though of course I am reasonable there (using Pimpl everywhere is quite a hassle).
It means that I prefer a forward declaration over an #include directive in my headers whenever I can get away with them.
Finally, I also use a visibility rule: I limit the scopes of my symbols as much as possible so that they do not pollute the outer scopes.
Putting it altogether:
// example_fwd.hpp
// Here necessary to forward declare the template class,
// you don't want people to declare them in case you wish to add
// another template symbol (with a default) later on
class MyClass;
template <class T> class MyClassT;
// example.hpp
#include "project/example_fwd.hpp"
// Those can't really be skipped
#include <string>
#include <vector>
#include "project/pimpl.hpp"
// Those can be forward declared easily
#include "project/foo_fwd.hpp"
namespace project { class Bar; }
namespace project
{
class MyClass
{
public:
struct Color // Limiting scope of enum
{
enum type { Red, Orange, Green };
};
typedef Color::type Color_t;
public:
MyClass(); // because of pimpl, I need to define the constructor
private:
struct Impl;
pimpl<Impl> mImpl; // I won't describe pimpl here :p
};
template <class T> class MyClassT: public MyClass {};
} // namespace project
// example_impl.hpp (not visible to clients)
#include "project/example.hpp"
#include "project/bar.hpp"
template <class T> void check(MyClass<T> const& c) { }
// example.cpp
#include "example_impl.hpp"
// MyClass definition
The lifesaver here is that most of the times the forward header is useless: only necessary in case of typedef or template and so is the implementation header ;)
To add more fun you can add .ipp files which contain the template implementation (that is being included in .hpp), while .hpp contains the interface.
As apart from templatized code (depending on the project this can be majority or minority of files) there is normal code and here it is better to separate the declarations and definitions. Provide also forward-declarations where needed - this may have effect on the compilation time.
Generally, when writing a new class, I will put all the code in the class, so I don't have to look in another file for it.. After everything is working, I break the body of the methods out into the cpp file, leaving the prototypes in the hpp file.
I personally do this in my header files:
// class-declaration
// inline-method-declarations
I don't like mixing the code for the methods in with the class as I find it a pain to look things up quickly.
I would not put ALL of the methods in the header file. The compiler will (normally) not be able to inline virtual methods and will (likely) only inline small methods without loops (totally depends on the compiler).
Doing the methods in the class is valid... but from a readablilty point of view I don't like it. Putting the methods in the header does mean that, when possible, they will get inlined.
I think that it's absolutely absurd to put ALL of your function definitions into the header file. Why? Because the header file is used as the PUBLIC interface to your class. It's the outside of the "black box".
When you need to look at a class to reference how to use it, you should look at the header file. The header file should give a list of what it can do (commented to describe the details of how to use each function), and it should include a list of the member variables. It SHOULD NOT include HOW each individual function is implemented, because that's a boat load of unnecessary information and only clutters the header file.
If this new way is really The Way, we might have been running into different direction in our projects.
Because we try to avoid all unnecessary things in headers. That includes avoiding header cascade. Code in headers will propably need some other header to be included, which will need another header and so on. If we are forced to use templates, we try avoid littering headers with template stuff too much.
Also we use "opaque pointer"-pattern when applicable.
With these practices we can do faster builds than most of our peers. And yes... changing code or class members will not cause huge rebuilds.
I put all the implementation out of the class definition. I want to have the doxygen comments out of the class definition.
IMHO, He has merit ONLY if he's doing templates and/or metaprogramming. There's plenty of reasons already mentioned that you limit header files to just declarations. They're just that... headers. If you want to include code, you compile it as a library and link it up.
Doesn't that really depends on the complexity of the system, and the in-house conventions?
At the moment I am working on a neural network simulator that is incredibly complex, and the accepted style that I am expected to use is:
Class definitions in classname.h
Class code in classnameCode.h
executable code in classname.cpp
This splits up the user-built simulations from the developer-built base classes, and works best in the situation.
However, I'd be surprised to see people do this in, say, a graphics application, or any other application that's purpose is not to provide users with a code base.
Template code should be in headers only. Apart from that all definitions except inlines should be in .cpp. The best argument for this would be the std library implementations which follow the same rule. You would not disagree the std lib developers would be right regarding this.
I think your co-worker is right as long as he does not enter in the process to write executable code in the header.
The right balance, I think, is to follow the path indicated by GNAT Ada where the .ads file gives a perfectly adequate interface definition of the package for its users and for its childs.
By the way Ted, have you had a look on this forum to the recent question on the Ada binding to the CLIPS library you wrote several years ago and which is no more available (relevant Web pages are now closed). Even if made to an old Clips version, this binding could be a good start example for somebody willing to use the CLIPS inference engine within an Ada 2012 program.