如何打破定义嵌套模板 class 的 headers 的循环依赖?
How to break circular dependency of the headers that defines nested template class?
编辑: 链接的不能解决这个特殊情况,因为在我的情况下有一个 nested 类型。
让我们想象一下情况是这样的:
//foo.hpp
//include guards
template <typename T>
class foo
{
class bar;
};
bar
的代码太大,所以我想(不是我,但没关系)到另一个文件。
那么,现在的情况是这样的:
//foo.hpp
#include <bar.hpp>
//include guards
template <typename T>
class foo
{
class bar;
};
//bar.hpp
#include <foo.hpp>
//include guards
template <typename T>
class foo::bar
{
//...
}
这肯定是循环依赖。但问题是编译器(clang 和 gcc)接受它。
我应该修复它还是没有什么可以修复的?如果是错误,我应该如何修复它?我是否应该将所有内容都转储到一个文件中,然后收工?
实际上,bar
是一个迭代器,我不想让它独立。
那里有 include 守卫,所以我想这就是阻止它被多次包含的原因,但循环依赖仍然让我担心。
嗯,一开始,你不能在没有 foo 的情况下使用 bar,当然...但是你想从 foo 中取出它 header。那么这个呢:
foo.hpp:
//include guards
// no, we won't include bar.hpp here...
template <typename T>
class foo
{
class bar;
};
// foo::bar is now predeclared
// and now we include bar:
#include "bar.hpp"
bar.hpp 不打算直接包含,所以我们只保留包含 foo:
//include guards
// don't need it:
//#include "foo.hpp"
template <typename T>
class foo::bar
{
//...
};
包括 foo 的任何人也将包括 bar。为了更清楚地表示 bar 不打算直接包含在内,我建议将其移动到具有适当名称的其他文件夹中,例如。 G。 "private".
不幸的是,我们可能会在 bar.hpp 中失去 IDE 对 foo 的支持。实际上,我们可以通过在 bar.hpp.
中包含 foo.hpp 来简单地取回它
但是为什么 - 然后我们又有一个循环包含???
嗯,是的,我们有,但是圈子坏了!请记住,bar.hpp 包含在 之后 foo 的声明!与普通的循环包含相比,这是这里的最大区别。那么从编译器看会发生什么:
- foo.hpp 包含在某处,foo 被声明,bar.hpp 添加之后.
- foo.hpp又被include了,但是定义了include guards,圆圈坏了。
从IDE来看正好相反:
* bar.hpp 包括 foo.hpp
* foo.hpp 再次包含 bar.hpp,但守卫已经定义。
所以我们很好......实际上,现在甚至可以包含 bar.hpp 并且仍然会得到 foo with.
编辑: 链接的不能解决这个特殊情况,因为在我的情况下有一个 nested 类型。
让我们想象一下情况是这样的:
//foo.hpp
//include guards
template <typename T>
class foo
{
class bar;
};
bar
的代码太大,所以我想(不是我,但没关系)到另一个文件。
那么,现在的情况是这样的:
//foo.hpp
#include <bar.hpp>
//include guards
template <typename T>
class foo
{
class bar;
};
//bar.hpp
#include <foo.hpp>
//include guards
template <typename T>
class foo::bar
{
//...
}
这肯定是循环依赖。但问题是编译器(clang 和 gcc)接受它。
我应该修复它还是没有什么可以修复的?如果是错误,我应该如何修复它?我是否应该将所有内容都转储到一个文件中,然后收工?
实际上,bar
是一个迭代器,我不想让它独立。
那里有 include 守卫,所以我想这就是阻止它被多次包含的原因,但循环依赖仍然让我担心。
嗯,一开始,你不能在没有 foo 的情况下使用 bar,当然...但是你想从 foo 中取出它 header。那么这个呢:
foo.hpp:
//include guards
// no, we won't include bar.hpp here...
template <typename T>
class foo
{
class bar;
};
// foo::bar is now predeclared
// and now we include bar:
#include "bar.hpp"
bar.hpp 不打算直接包含,所以我们只保留包含 foo:
//include guards
// don't need it:
//#include "foo.hpp"
template <typename T>
class foo::bar
{
//...
};
包括 foo 的任何人也将包括 bar。为了更清楚地表示 bar 不打算直接包含在内,我建议将其移动到具有适当名称的其他文件夹中,例如。 G。 "private".
不幸的是,我们可能会在 bar.hpp 中失去 IDE 对 foo 的支持。实际上,我们可以通过在 bar.hpp.
中包含 foo.hpp 来简单地取回它但是为什么 - 然后我们又有一个循环包含???
嗯,是的,我们有,但是圈子坏了!请记住,bar.hpp 包含在 之后 foo 的声明!与普通的循环包含相比,这是这里的最大区别。那么从编译器看会发生什么:
- foo.hpp 包含在某处,foo 被声明,bar.hpp 添加之后.
- foo.hpp又被include了,但是定义了include guards,圆圈坏了。
从IDE来看正好相反: * bar.hpp 包括 foo.hpp * foo.hpp 再次包含 bar.hpp,但守卫已经定义。
所以我们很好......实际上,现在甚至可以包含 bar.hpp 并且仍然会得到 foo with.