I use several 3rd party libraries like boost, I have one class in my project, let's say it called "MyClass"
All the public functions of "MyClass" use only standard types (int,char,string), but the private functions use smart pointers from boost, and other algorithms from other libraries.
So before i write the declaration of the class (and it's functions) in the H file i write several include files.
To make the project compile i add some Additional include libraries to the project properties.
And everything works fine.
The problem is that when i want to use this class from another project called USERPROJECT (the class is extern) i need to include the MyClass.h file in the USERPROJECT project, and then nothing will compile because MyClass.h includes boost and other things that are not configured in the USERPROJECT (i didn't configure the additional include libraries here, and i don't want to because he doesn't need to know them, they are in the private functions of the MyClass class).
What i the solution ?
should i split MyClass to 2 class one for interface and one for implementation ?
should i remove all the includes from the H and MyClass and use forward declaration ? (i tried but failed to compile it)
is there a better solution
Thanks in advance
You can create compiler firewalls by using the pimpl idiom:
// header file
class C
{
public:
...
private:
struct Impl;
boost::scoped_ptr<Impl> m;
};
// cpp file
struct C::Impl
{
// data member that were in C previously go here //
};
This way the code using your header file does not see the guts of your class. This idiom is explained in detail here. However, you can still get linking errors, if you use boost libraries that need to be linked in. If you use header-only parts of boost only, then there should be no problem.
The ideal is that every external component is accessible in every project. (And all are compiled with compatible options, etc).
If you can push toward that, your problem will be solved. And problems of other people around who wanted to use boost but faced this same impediment.
If you can't do that, you might still have solution using pimpl, but it is adds a deal of complexity, maintenance overhead and reduces readablity to some extent. And depending on what you use from boost, may only solve the compile part of the issue, as linking may require some extra lib. (unless your thing is self-contained, like a DLL)
For the latter case, if linking happens at client site, smuggling the lib is mandatory, but then it's the same amount of work to have the full boost, and avoid the chaos. So before action do some research.
Related
I am trying to write my first (very) small, for now only self-use, library. In the process I came across questions regarding how I should separate my headers/source code/object files in a logical way.
To be more specific, I'm writing a small templated container class, so for one I have to include the implementation of this class inside its header.
I have a directory structure like this:
include/ - "public" .hh header files included by extern projects
src/ - .cc files for implementation (+ "private" .hh header files?)
lib/ - .o compiled library files linked by extern projects
I am already not sure if this makes sense.. in my case I also wrote some helper-classes used by my templated container class, one of which is something like an iterator. So I have the following files:
container.hh
container.cc
container_helper.hh
container_helper.cc
container_iterator.cc
container_iterator.hh
While I want to have access to their functions in external projects (e.g. incrementing the iterator), it makes no sense to me that a project would specifically
#include "container_iterator.hh"
Now, since I want projects to be able to use the container class, I put "container.hh" and "container.cc" (since it must be included in "container.hh" because of the template) into the "include/" directory, which is then included by other projects.
Now my confusion arises.. the container class needs access to the helper classes, but I don't want other projects to only include the helper classes, so it seems wrong to place also the helper classes into "include/" directory. Instead, I would place them in "src/".
But if I do this, then to include these in "include/container.cc" I have to use relative filepath
#include "../src/container_iterator.hh"
But now if I "distribute" my library to an external project, i.e. I only make the "include/" directory visible to the compiler, it will not compile (?), since "../src/container_iterator.hh" does not exist.
Or do I compile the container class and put it as library into "lib/", which is then linked by other projects? But even then do I not still need to include the header "container.hh", to be able to find the function declarations, which leads to the same problem?
Basically I'm lost here.. how does the standard do this? E.g. I can
#include <vector>
, but I don't know of any header to only include std::vector::iterator, which would make no sense to do so.
At some point in my expanation I must be talking nonsense but I cannot find where. I think I understand what a header and a library is/should be, but when it comes to how to design and/or "distribute" them for an actual project, I am stuck. I keep coming across problems like this even when I started learning C++ (or any language for that matter), no course / no book ever seems to explain how to implement all these concepts, only how to use them when they already exist..
Edit
To clarify my confusion (?) more.. (this got a bit too long for a comment) I did read before to put implementation of templated classes into the header, which is why I realized I need to at least put the "container.cc" into the include/ dir. While I don't particularly like this, at least it should be clear to an external user to not include ".cc" files.
Should I take this also as meaning that it never makes sense to compile templated classes into a library, since all of it will be always included?
(So templated code is always open-source? ..that sounds wrong?)
And in this case I still wonder how STL does it, does vector declare & define its iterator in its own header? Or is there a separate header for vector::iterator I could include, it just would make no sense to do so?
Hopefully I explained my intent clearly, please comment if not.
Thanks for any help!
In my experience, the most common method to handle your problems is to have headers with the template declarations and documentation (your .hh files), which also include .inc or .tcc (your preference) files with the template definitions. I also suggest keeping all files that may be included by external projects in the same folder, but if you want to keep things clean, put your .inc/.tcc files in a folder within include called detail (or bits if you like GNU style).
Putting stuff in a detail folder,
and using a weird extension should deter users enough.
To answer your other questions:
Due to the nature of C++ templates,
either the entire source of the parts of a template you use
must be present in the translation unit (ie. #include'd),
or you can use explicit instantiation
for a finite number of arguments
(this is not generally useful for a container, though).
So, for most purposes, you have to distribute a template's source, though,
of course, (as mentioned in the comments) "open source" is about licence,
not source visibility.
As for the standard libraries, lets use <vector> as an example.
The GNU C++ Library has a vector file that (among other things) includes
bits/stl_vector.h which has the declarations & documentation,
and includes a bits/vector.tcc that has the definitions.
LLVM's libc++ just has one giant file,
but puts the declarations at the top (without documentation!)
and all the definitions at the bottom.
As a final note, there are lots of open source C++ libraries that you can take a look at for inspiration in the future!
I have trouble understanding the sentence with respect to inline and customers binary compatibility. Can someone please explain?
C++ FAQ Cline, Lomow:
When the compiler synthesizes the copy constructor, it makes them inline. If your classes are exposed to your customers ( for example, if your customers #include your header files rather than merely using an executable, built from your classes ), your inline code is copied into your customers executables. If your customers want to maintain binary compatibilty between releases of your header files, you must not change an inline functions that are visible to the customers. Because of this, you will want an explicit, non inline version of the copy constructor, that will be used directly by the customer.
Binary compatibility for dynamic libraries (.dll, .so) is often an important thing.
e.g. you don't want to have to recompile half the software on the OS because you updated some low level library everything uses in an incompatible way (and consider how frequent security updates can be). Often you may not even have all the source code required to do so even if you wanted.
For updates to your dynamic library to be compatible, and actually have an effect, you essentially can not change anything in a public header file, because everything there was compiled into those other binaries directly (even in C code, this can often include struct sizes and member layouts, and obviously you cant remove or change any function declarations either).
In addition to the C issues, C++ introduces many more (order of virtual functions, how inheritance works, etc.) so it is conceivable that you might do something that changes the auto generated C++ constructor, copy, destructor etc. while otherwise maintaining compatibility. If they are defined "inline" along with the class/struct, rather than explicitly in your source, then they will have been included directly by other applications/libraries that linked your dynamic library and used those auto generated functions, and they wont get your changed version (which you maybe didn't even realise has changed!).
It is referring to problems that can occur between binary releases of a library and header changes in that library. There are certain changes which are binary compatible and certain changes which are not. Changes to inline functions, such as an inlined copy-constructor, are not binary compatible and require that the consumer code be recompiled.
You see this within a single project all the time. If you change a.cpp then you don't have to recompile all of the files which include a.hpp. But if you change the interface in the header, then any consumer of that header typically needs to be recompiled. This is similar to the case when using shared libraries.
Maintaining binary compatibility is useful for when one wants to change the implementation of a binary library without changing its interface. This is useful for things like bug fixes.
For example say a program uses liba as a shared library. If liba contains a bug in a method for a class it exposes, then it can change the internal implementation and recompile the shared library and the program can use the new binary release of that liba without itself being recompiled. If, however, liba changes the public contract such as the implementation of an inlined method, or moving an inlined method to being externally declared, then it breaks the application binary interface (ABI) and the consume program must be recompiled to use the new binary version of the liba.
Consider the following code compiled into static library:
// lib.hpp
class
t_Something
{
private: ::std::string foo;
public: void
Do_SomethingUseful(void);
};
// lib.cpp
void t_Something::
Do_SomethingUseful(void)
{
....
}
// user_project.cpp
int
main()
{
t_Something something;
something.Do_SomethingUseful();
t_Something something_else = something;
}
Now when t_Something class fields changes somehow, for example a new one is added we get in a situation where all the user code have to be recompiled. Basically constructors implicitly generated by compiler "leaked" from our static library to user code.
I think I understand what this passage means. By no means I am endorsing this, though.
I believe, they describe the scenario when you are developing a library and provide it to your customers in a form of header files and pre-compiled binary library part. After customer has done initial build, they are expected to be able to substitute a binary part with a newer one without recompiling their application - only relink would be required. The only way to achieve that would be to guarantee that header files are immutable, i.e. not changed between versions.
I guess, the notion of this would come from the fact that in 98 build systems were not smart enough and would not be able to detect change in header file and trigger recompilation of affected source file.
Any and all of that is completely moot nowadays, and in fact, goes again the grain - as significant number of libraries actually try hard to be header-only libraries, for multiple reasons.
I have two libraries (third-party), and within each of these libs they have defined two classes with same name (in header files).
// Lib A, HeaderA.h
struct mycompare
{
//Some code
};
// Lib B, HeaderB.h
struct mycompare
{
//Same code
};
Please note that, in both libs, mycompare name and the implementation is same. How to use both header files same time ?
Assuming you can't edit the headers/libraries:
indirection: create your own out-of-line wrapper for the simpler of A and B, which includes HeaderA.h or HeaderB.h only in the implementation.
this is similar to but much less work and coupling than Als's option 2 ;-)
shameless hackery: include HeaderA.h, then #define mycompare mycompare_duplicate before including HeaderB.h, then #undef mycompare. This could bite you if one of the implementations later changes, and may not be possible if the header later uses the symbol itself (e.g. as a function argument, where type name-mangling would differ and prevent your calls being resolved).
If you can edit the libraries, then obviously the best long-term option is to put their functionality into separate namespaces.
A quick workaround is to simply wrap them in a namespace. That might be simple enough, depending on how complicated the headers are. Alternatively, consider writing your own header with this particular struct (if you know it's going to stay the same) and cast when passing to each of them.
That said, it's highly untypical to have this case. Are you sure that library B is not dependent on A or vice versa? In that case, the only thing that might be broken is some #define USE_EXTERNAL_A or so. A typical example are libraries that include zlib unless you provide them with one.
Just make a third header, move redundant definitions in it(only once); then include this header into the originals. It should work.
I have a static library that I am building in C++. I have separated it into many header and source files. I am wondering if it's better to include all of the headers that a client of the library might need in one header file that they in turn can include in their source code or just have them include only the headers they need? Will that cause the code to be unecessary bloated? I wasn't sure if the classes or functions that don't get used will still be compiled into their products.
Thanks for any help.
Keep in mind that each source file that you compile involves an independent invocation of the compiler. With each invocation, the compiler has to read in every included header file, parse through it, and build up a symbol table.
When you use one of these "include the world" header files in lots of your source files, it can significantly impact your build time.
There are ways to mitigate this; for example, Microsoft has a precompiled header feature that essentially saves out the symbol table for subsequent compiles to use.
There is another consideration though. If I'm going to use your WhizzoString class, I shouldn't have to have headers installed for SOAP, OpenGL, and what have you. In fact, I'd rather that WhizzoString.h only include headers for the types and symbols that are part of the public interface (i.e., the stuff that I'm going to need as a user of your class).
As much as possible, you should try to shift includes from WhizzoString.h to WhizzoString.cpp:
OK:
// Only include the stuff needed for this class
#include "foo.h" // Foo class
#include "bar.h" // Bar class
public class WhizzoString
{
private Foo m_Foo;
private Bar * m_pBar;
.
.
.
}
BETTER:
// Only include the stuff needed by the users of this class
#include "foo.h" // Foo class
class Bar; // Forward declaration
public class WhizzoString
{
private Foo m_Foo;
private Bar * m_pBar;
.
.
.
}
If users of your class never have to create or use a Bar type, and the class doesn't contain any instances of Bar, then it may be sufficient to provide only a forward declaration of Bar in the header file (WhizzoString.cpp will have #include "bar.h"). This means that anyone including WhizzoString.h could avoid including Bar.h and everything that it includes.
In general, when linking the final executable, only the symbols and functions that are actually used by the program will be incorporated. You pay only for what you use. At least that's how the GCC toolchain appears to work for me. I can't speak for all toolchains.
If the client will always have to include the same set of header files, then it's okay to provide a "convience" header file that includes others. This is common practice in open-source libraries. If you decide to provide a convenience header, make it so that the client can also choose to include specifically what is needed.
To reduce compile times in large projects, it's common practice to include the least amount of headers as possible to make a unit compile.
what about giving both choices:
#include <library.hpp> // include everything
#include <library/module.hpp> // only single module
this way you do not have one huge include file, and for your separate files, they are stacked neatly in one directory
It depends on the library, and how you've structured it. Remember that header files for a library, and which pieces are in which header file, are essentially part of the API of the library. So, if you lead your clients to carefully pick and choose among your headers, then you will need to support that layout for a long time. It is fairly common for libraries to export their whole interface via one file, or just a few files, if some part of the API is truly optional and large.
A consideration should be compilation time: If the client has to include two dozen files to use your library, and those includes have internal includes, it can significantly increase compilation time in a big project, if used often. If you go this route, be sure all your includes have proper include guards around not only the file contents, but the including line as well. Though note: Modern GCC does a very good job of this particular issue and only requires the guards around the header's contents.
As to bloating the final compiled program, it depends on your tool chain, and how you compiled the library, not how the client of the library included header files. (With the caveat that if you declare static data objects in the headers, some systems will end up linking in the objects that define that data, even if the client doesn't use it.)
In summary, unless it is a very big library, or a very old and cranky tool chain, I'd tend to go with the single include. To me, freezing your current implementation's division into headers into the library's API is bigger worry than the others.
The problem with single file headers is explained in detail by Dr. Dobbs, an expert compiler writer. NEVER USE A SINGLE FILE HEADER!!! Each time a header is included in a .cc/.cpp file it has to be recompiled because you can feed the file macros to alter the compiled header. For this reason, a single header file will dramatically increase compile time without providing any benifit. With C++ you should optimize for human time first, and compile time is human time. You should never, because it dramatically increases compile time, include more than you need to compile in any header, each translation unit(TU) should have it's own implementation (.cc/.cpp) file, and each TU named with unique filenames;.
In my decade of C++ SDK development experience, I religiously ALWAYS have three files in EVERY module. I have a config.h that gets included into almost every header file that contains prereqs for the entire module such as platform-config and stdint.h stuff. I also have a global.h file that includes all of the header files in the module; this one is mostly for debugging (hint enumerate your seams in the global.h file for better tested and easier to debug code). The key missing piece here is that ou should really have a public.h file that includes ONLY your public API.
In libraries that are poorly programmed, such as boost and their hideous lower_snake_case class names, they use this half-baked worst practice of using a detail (sometimes named 'impl') folder design pattern to "conceal" their private interface. There is a long background behind why this is a worst practice, but the short story is that it creates an INSANE amount of redundant typing that turns one-liners into multi-liners, and it's not UML compliant and it messes up the UML dependency diagram resulting in overly complicated code and inconsistent design patterns such as children actually being parents and vice versa. You don't want or need a detail folder, you need to use a public.h header with a bunch of sibling modules WITHOUT ADDITIONAL NAMESPACES where your detail is a sibling and not a child that is in reatliy a parent. Namespaces are supposed to be for one thing and one thing only: to interface your code with other people's code, but if it's your code you control it and you should use unique class and funciton names because it's bad practice to use a namesapce when you don't need to because it may cause hash table collision that slow downt he compilation process. UML is the best pratice, so if you can organize your headers so they are UML compliant then your code is by definition more robust and portable. A public.h file is all you need to expose only the public API; thanks.
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.