1

I know there are many answers on this site about circular dependency, but none that I found can solve my problem, mainly because my definitions are inlined in the headers.

I am writing a library in C++11. For simplification, I have two classes:

  • Exception in Exception.hpp
  • CallStack in CallStack.hpp.

The dependencies are:

  • Exception makes heavy use of CallStack (both in declarations and definitions it needs a complete type of CallStack) so Exception.hpp includes CallStack.hpp.
  • CallStack doesn't need Exception at all in it's declaration. It just needs to throw an Exception (calls a non-default Exception constructor) in one of the member definition (operator[]), so it needs a complete type of Exception in a definition.

I know that if I write the definition in a .cpp file, I resolve the problem, but since all methods and constructors don't have more than 2 lines, I have chosen to define them inline, which means that they need to be defined in the .hpp header.

The solution to have a forward declaration before the declaration and to include the other header between the declaration and the definition doesn't work, as, I have said, Exception needs a complete type of CallStack in its declaration.

bolov
  • 72,283
  • 15
  • 145
  • 224
  • What advantage are you trying to achieve by inlining the methods? Performance? Avoiding creating and extra file? Something else? – Dale Wilson Jan 14 '14 at 23:10
  • @DaleWilson performance, since the methods are 1 or 2 lines long. I do have the `.cpp` file that has a longer method. – bolov Jan 14 '14 at 23:14
  • For what it's worth, the performance impact is almost certainly not worth worrying about, and furthermore, a good optimizing compiler may end up inlining the functions anyway (see: http://stackoverflow.com/questions/1626248/does-gcc-inline-c-functions-without-the-inline-keyword). – CmdrMoozy Jan 14 '14 at 23:18
  • 2
    Is performance critical? Have you have profiled your code and determined that inlining these methods buys you a significant improvement? If both answers are yes, then you can do some ugly things to make this work. But if you can't answer both questions with a resounding "Yes" then @Reed is right, put the implementation in the cpp file. (and move on to a more interesting challenge.) – Dale Wilson Jan 14 '14 at 23:19
  • @CmdrMoozy if a definition is in a `.cpp` file, the compiler can't inline it for external compilation units, and this is a library – bolov Jan 14 '14 at 23:21
  • @DaleWilson I will put it the cpp file – bolov Jan 14 '14 at 23:21
  • 1
    @bolov: Ah, but the linker can if you turn on the right optimization. (see Whole Program Optimization, or similar options.) – Dale Wilson Jan 14 '14 at 23:22

2 Answers2

4

I know that if I write the definition in a .cpp file, I resolve the problem, but since all methods and constructors don't have more than 2 lines, I have chosen to define them inline, which means that they need to be defined in the .hpp header.

Writing the definition in the .cpp file is really the correct solution. You need to forward declare the Exception type in CallStack, and move your implementation details for the function(s) that use Exception into the .cpp files.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
2

Create separate headers for declarations (foo-declarations.hpp) and inlines (foo-inlines.hpp), and include in the order:

#include "Callstack-declarations.hpp"
#include "Exception-declarations.hpp"
#include "Callstack-inlines.hpp"
#include "Exception-inlines.hpp"

Stick those four lines in another header "Callstack+Exception.hpp" if you don't want to repeat four lines everywhere. Or for minimal inclusion:

// Exception.hpp
#include "Callstack-declarations.hpp"
#include "Exception-declarations.hpp"
#include "Exception-inlines.hpp"
// Callstack.hpp
#include "Callstack-declarations.hpp"
#include "Exception-declarations.hpp"
#include "Callstack-inlines.hpp"
Casey
  • 41,449
  • 7
  • 95
  • 125
  • This is a very interesting solution, however, I don't like I have to create that many headers. I have chosen to put the definition in the `.cpp` file. – bolov Jan 14 '14 at 23:31