Question

I am developing a fairly large C++ support library, and have found myself moving towards a header-only approach. In C++ this almost works because you can implement where you define in classes. For templated methods, the implementation has to be in the same file anyway, so I find that it is much easier to just keep the implementation with the definition.

However, there are several times where "sources" must be used. As just one example, circular dependencies sometimes occur and the implementation has to be written outside the class definition. Here is how I am handling it:

//part of libfoo.h
class Bar
{
  void CircularDependency(void);
};

#ifdef LIBFOO_COMPILE_INLINE
void Bar::CircularDependency(void)
{
  //...
}
#endif

Then the project that uses libfoo would do the following in main.cpp:

//main.cpp
#define LIBFOO_COMPILE_INLINE
#include "libfoo.h"

And in any other .cpp:

//other.cpp
#include "libfoo.h"

The point is that the compile-inline section only gets compiled once (in main.cpp).

And finally my question: is there a name for this idiom or any other projects that work this way? It just seems to be a natural outcome of the implementation and definition being blurred by templating and class methods. And: are there any reasons why this is a bad idea or why it would potentially not scale well?

Quick aside: I know that many coders, with good reason, prefer their headers to resemble interfaces and not implementations, but IMHO documentation generators are better suited to describing interfaces because I like to hide private members all together :-)

Was it helpful?

Solution

You should be able to use the inline keyword if the circular dependency problem is resolved by the time the definition of Bar::CircularDependency() would show up in the libfoo.h header:

//part of libfoo.h
class Bar
{
  void CircularDependency(void);
};


// other stuff that 'resolves' the circular dependency
// ...
// ...

inline void Bar::CircularDependency(void)
{
  //...
}

That would make your library easier to use (the user wouldn't need to deal with the fact that LIBFOO_COMPILE_INLINE needed to be defined in exactly one place where the header is included).

OTHER TIPS

Circular dependencies are not really a problem as you can forward decalre that functions are inline. I wouldn't really suggest this, though: while the "source-less" approach initially makes it easier to use a library coming from somewhere, it causes longer compile times and tighter coupling between files. In a huge source base this is essentially killing the hOpe to get code build in reasonable times. Sure huge only starts at a couple millions lines of code but who cares about trivial programs...? (and, yes, the place I work at has several tens of millions lines of code being build into single executables)

My reasons for why this is a bad idea.

Increase in compile time

Every individual compilation unit that includes the header should compile all the header files in addition to the source in itself. This would probably increase the compile time and might be frustrating while testing your code, with small changes. One could argue the compiler might optimize it, but IMO it could not optimize it beyond a point.

Bigger code segment

If all the functions are written inline, it means that the compiler has to put all that code wherever the function is called. This is going to blow up the code segment and it would affect the load time of the program and the program would take more memory.

Creates dependency in client code with tight coupling

Whenever you change your implementation, every client should get updated (by re compiling the code). But if the implementation has been put in an independent shared object (.so or .dll), the client should just link to the new shared object.

Also I am not sure why one would do this.

//main.cpp
#define LIBFOO_COMPILE_INLINE
#include "libfoo.h"

If at all one has to do this, (s)he could have simply put the implementation code in main.cpp itself. Anyway, you could define LIBFOO_COMPILE_INLINE only in one compilation unit. Otherwise you will duplicate definitions.

I am actually much interested in developing a idiom to write cohesive template code. Sometime in future, C++ compiler should support writing cohesive templates. By this, I mean the client need not have to recompile the code, whenever template implementation in modified.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top