Проблема циклической зависимости C ++ с шаблонами функций

У меня есть несколько классов в проекте, над которым я работаю; первый — это класс Solver, изначально с шаблоном функции, полное определение которого находится в заголовочном файле Solver, вот так (просто показывая все необходимое):

solver.h

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

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

Теперь класс A используется в качестве параметра шаблона для шаблона функции решения следующим образом:

хиджры

#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);
}

Так что все в порядке, как и сейчас, но для целей проекта мне нужно перенести определение шаблона функции solve () в файл реализации (solver.cpp) из файла заголовка. Насколько я понимаю, я могу делать это до тех пор, пока я добавляю строки, которые явно указывают, какие типы будут использоваться с шаблоном функции, следующим образом:

solver.cpp

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

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

Однако это не работает, когда я пытаюсь скомпилировать решатель, потому что для того, чтобы указать A как тип, который я хочу использовать в качестве параметра шаблона в solve.cpp, мне нужно, чтобы A не был неполным типом. Но A требует Solver для того, чтобы даже компилировать — поэтому я считаю, что у меня круговая зависимость. Есть ли способ обойти эту проблему?

Я относительно новичок во всем этом, так что успокойся, пожалуйста 🙂 Большое спасибо.

3

Решение

Самот почти прав, тебе нужно class A; («предварительная декларация»). Но только перед его использованием, а не перед классом Solver:

отредактированный В ответ на комментарии ваш минимальный пример кода был слишком минимальным 🙂 Реальная проблема была Страж заголовка:

#ifndef SOLVER_H_INCLUDED_
#define SOLVER_H_INCLUDED_

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

#endif // SOLVER_H_INCLUDED_

А также

// 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&);

Это будет работать

// main.cpp
#include "A.h"
int main()
{
A a;
a.doSomething();
}
2

Другие решения

Лучший способ обойти циклические зависимости — сделать это:

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
}
0

Что вы можете сделать, это:

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
}

и 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
0
По вопросам рекламы [email protected]