我(抽象地)有3个标头,其中两个包含单个变体,这些变体从另一个调用另一个。这些的主要结构如下:
AB.hpp
#ifndef AB
#define AB
//#include "CD.hpp"
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){
os << s.top();
/*more code..*/
return os;
}
};
using AB_var = std::variant<A, B>;
std::ostream &operator<<(std::ostream &os, AB_var const &v) {
switch(v.index()){
case 0: // A
os << std::get<A>(v);
break;
case 1: // B
os << std::get<B>(v);
break;
default:
throw std::bad_variant_access();
}
return os;
}
}
#endif
CD.hpp
#ifndef CD
#define CD
//#include "AB.hpp"
namespace HELLO {
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){
os << s.top();
os << t.top();
/*more code..*/
return os;
}
}
struct D{/*...*/}
std::ostream &operator<<(std::ostream &os, CD_var const &v) {
switch(v.index()){
case 0: // C
os << std::get<C>(v);
break;
case 1: // D
os << std::get<D>(v);
break;
default:
throw std::bad_variant_access();
}
return os;
}
}
#endif
ABCD.hpp使用AB.hpp和CD.hpp中的两个元素。
现在的问题是,经过数小时的思考,我找不到正确链接这些标头的方法。无论我如何链接它们,由于此原因它都会返回带有大量错误消息的错误。我想将AB
和CD
分开,因为它们具有不同的功能。请给我一种使此代码起作用的方法。谢谢。
答案 0 :(得分:2)
一种可能的解决方案是将标头拆分为正向声明和实现:
// AB_forward.hpp
#pragma once
#include <ostream>
#include <variant>
struct A;
struct B;
using AB_var = std::variant<A, B>;
std::ostream & operator<<(std::ostream &, AB_var const &);
// CD_forward.hpp
#pragma once
#include <ostream>
#include <variant>
struct C;
struct D;
using CD_var = std::variant<C, D>;
std::ostream & operator<<(std::ostream &, CD_var const &);
// AB.hpp
#pragma once
#include "AB_forward.hpp"
#include "CD_forward.hpp"
#include <stack>
struct A { /*...*/ };
struct B {
std::stack<CD_var> s;
friend std::ostream & operator<<(std::ostream &, B const &);
};
// CD.hpp
#pragma once
#include "AB_forward.hpp"
#include "CD_forward.hpp"
#include <stack>
struct C {
std::stack<AB_var> s; std::stack<CD_var> t;
friend std::ostream & operator<<(std::ostream &, C const &);
};
struct D { /*...*/ };
// AB_CD.hpp <- implementations are here
#include "AB.hpp"
#include "CD.hpp"
std::ostream & operator<<(std::ostream &, B const &) { /* ... */ }
std::ostream & operator<<(std::ostream &, AB_var const &) { /* ... */ }
std::ostream & operator<<(std::ostream &, C const &) { /* ... */ }
std::ostream & operator<<(std::ostream &, CD_var const &) { /* ... */ }
// main.cpp
#include "AB_CD.hpp"
/* ... */
答案 1 :(得分:1)
您要做的就是将标头拆分为.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;
}
}
有关编译时间的更多信息:Headers Including Each Other in C++