Question

I have several classes in a project I'm working on; the first is a Solver class, originally with a function template whose full definition is in the Solver header file, like so (just showing the bare necessities):

solver.h

class Solver {
  public:
    template<typename T>
    void solve(T t);
}

template<typename T>
void Solver::solve(T t) {
  // implementation here
}

Now, class A is used as template parameter for the solve function template as follows:

A.h

#include "solver.h"

class A {
  private:
    Solver s;  //s is instantiated in constructor

  public:
    void doSomething();
}

A.cpp

void A::doSomething() {
  s.solve<A&>(*this);
}

So this is all fine and dandy as it is now, but for the purposes of the project, I need to move the definition of the solve() function template into an implementation file (solver.cpp) from the header file. As I understand it, I can do this as long as I add lines that explicitly state what types will be used with the function template, as follows:

solver.cpp

template<typename T>
void Solver::solve(T t) {
  // implementation here
}

template void Solver::solve<A&>(A& a);

However this doesn't work when I try to compile solver, because in order to specify A as a type I want to use as a template parameter in solve.cpp, I need to have A not be an incomplete type. But A requires Solver in order to even compile - so I believe I have a circular dependency. Is there any way I can get around this issue?

I'm relatively new to all this, so take it easy on me please :) Much thanks.

Was it helpful?

Solution

Samoth is nearly right, you need class A; ("forward declaration"). But only before you use it, not before the Solver class:

Edited In response to comments, your minimal code sample was too minimal :) The real problem was Header Guards:

#ifndef SOLVER_H_INCLUDED_
#define SOLVER_H_INCLUDED_

class Solver {
  public:
    template<typename T>
    void solve(T t);
};

#endif // SOLVER_H_INCLUDED_

And

// A.h
#ifndef A_H_INCLUDED_
#define A_H_INCLUDED_

#include "Solver.h"

class A {
  private:
    Solver s;  //s is instantiated in constructor

  public:
    void doSomething();
};

#endif // A_H_INCLUDED_


// Solver.cpp
#include "Solver.h"

#include "A.h"

template<typename T>
void Solver::solve(T t) {
  // implementation here
}

// explicit instantiations    
template void Solver::solve<int>(int);
//   ... 
template void Solver::solve<A&>(A&);

This will work

// main.cpp
#include "A.h"

int main()
{
    A a;
    a.doSomething();
}

OTHER TIPS

The best way to pass-by circular dependencies is to do this :

class A; // before the class Solver

class Solver {
  public:
    template<typename T>
    void solve(T t);
}

template<typename T>
void Solver::solve(T t) {
  // implementation here
}

What you can do is:

solver.h

   #ifndef SOLVER_H_INCLUDED_
   #define SOLVER_H_INCLUDED_
    class Solver {
    public:
      template<typename T>
      void solve(T t);

    };
    #include "solver.cpp"
    #endif

solver.cpp

#include "solver.h"

template<typename T>
void Solver::solve(T t) {
  // implementation here
}

and a.hpp

    #ifndef A_H_INCLUDED_
    #define A_H_INCLUDED_
    #include "solver.h"
    class A {
    private:
      Solver s;  //s is instantiated in constructor

    public:
      void doSomething()
      {
        s.solve(*this);
      }
    };
   #endif
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top