Все, что вам нужно сделать, это разделить ваши заголовки на файлы .hpp & .cpp, объявления принадлежат файлам .hpp, а реализации принадлежат файлам .cpp, и в этот момент в AB.hpp включают CD.h, ив CD. cpp включает AB.hpp.Это должно сделать работу.
РЕДАКТИРОВАТЬ: вы также должны использовать предварительное объявление в файле CD.hpp для использования AB_variant.
Примерно так:
AB.hpp
#ifndef PROJECT_AB_H
#define PROJECT_AB_H
#include "CD.h"
namespace HELLO {
struct A;
struct B;
struct A {/*...*/};
struct B {
std::stack<CD_var> s;
friend std::ostream &operator<<(std::ostream &os, B const &b);
};
using AB_var = std::variant<A, B>;
std::ostream &operator<<(std::ostream &os, AB_var const &v);
}
#endif
AB.cpp
#include "AB.h"
namespace HELLO {
std::ostream &operator<<(std::ostream &os, AB_var const &v) {/*...*/}
std::ostream &operator<<(std::ostream &os, B const &b) {
//The right using is: b.s.top();
/*more code..*/
return os;
}
}
CD.hpp
#ifndef PROJECT_CD_H
#define PROJECT_CD_H
namespace HELLO {
struct A;
struct B;
using AB_var = std::variant<A, B>;
struct C;
struct D;
using CD_var = std::variant<C, D>;
std::ostream &operator<<(std::ostream &os, CD_var const &v);
struct C {
std::stack<AB_var> s;
std::stack<CD_var> t;
friend std::ostream& operator<<(std::ostream &os, C const &c);
};
struct D {/*...*/};
/*...*/
}
#endif
CD.cpp
#include "CD.h"
#include "AB.h"
namespace HELLO {
std::ostream &operator<<(std::ostream &os, CD_var const &v) {/*...*/}
std::ostream& operator<<(std::ostream &os, C const &c) {
//The right using is: c.s.top();
//The right using is: c.t.top();
/*more code..*/
return os;
}
}
Подробнее о сборникевремя: Заголовки, включающие друг друга в C ++