我有以下架构问题,导致 header 的循环依赖。它涉及通用编程和 C++ 模板。所以:
- 我定义了聚合在节点中的属性
- 这些属性被定义为模板
- 此模板的参数之一是属性处理的数据类型系列
- 每个类型系列都有一个专门化的属性模板:
- 基本类型(浮点型、整数型...)
- 指向节点的指针
- 数据类型系列是使用元编程计算的
- 基本类型 -> 模板参数 = 0
- 指向节点的指针 -> 模板参数 = 1
- 未处理的类型 -> 模板参数 = -1
- 我的循环依赖与类型族“指向节点的指针”有关
- 为了确定指针的类型是否是节点,我有编译时代码来检查类 ConcreteNode 是否派生自类 Node
- 为了确定这一点,编译器需要知道 ConcreteNode 的声明
- 因此,当定义包含指向 ConcretNode 的指针的属性时,我必须包含 ConcreteNode 的 header ,而不是简单地向前声明 ConcreteNode
- 如果 ConcreteNodeA 包含指向 ConcreteNodeB 的指针,并且反过来 ConcreteNodeB 包含指向 ConcreteNodeA 的指针,则会出现问题
- 在这种情况下,我需要将 ConcreteNodeB 的 header 包含在 ConcreteNodeA 的 header 中,反之亦然
- 这会导致 header 的循环依赖
这里有一些代码来说明这一切:
// Property.hpp
class PropertyBase
{
// Some code common to all properties.
}
template <class T, int typeFamily = TypeFamily<T>::value >
class Property : public PropertyBase
{
// Default template to catch errors.
};
template <class T>
class Property<T, 0> : public PropertyBase
{
// Data is a base type.
T* m_dataRef;
// Some basic types-specific stuff.
};
template <class T>
class Property<T*, 1> : public PropertyBase
{
// Data is a pointer to a concrete node.
T** m_dataRef;
// Some pointer to node-specific stuff.
};
// ConcreteNodeA.h
#include "ConcreteNodeB"
class ConcreteNodeA : public Node
{
protected:
Property<ConcreteNodeB*>& m_nodeB;
};
// ConcreteNodeB.h
#include "ConcreteNodeA"
class ConcreteNodeB : public Node
{
protected:
Property<ConcreteNodeA*>& m_nodeA;
};
显然我的真实代码比这更复杂:
- 即仅当基本类型属于已处理类型列表的一部分时才会对其进行处理
- 我没有公开用于确定一个类是否派生于另一个类的元代码
- 我想人们愿意帮助我了解这件事
- 不这样做的人不应受其困扰
有人知道如何声明我的属性而不会出现此循环依赖问题吗?此刻我陷入困境......
谢谢!
-----编辑------
以下内容
TypeFamily<T>::value
是元代码,如果 T 是受支持的基类型,则返回 0;如果 T 是指向从节点派生的类的指针,则返回 1;在其他情况下返回 -1。
-----编辑------
我无法对 ConcreteNodeA 和 ConcreteNodeB 使用前向声明,因为在这种情况下,编译器无法“理解”从 Node 派生的 ConcreteNodeA 和 ConcreteNodeB。因此 TypeFamily::value 将返回 -1,而不是 1。因此,所选模板将是默认的“catch-errors”模板,而不是我想要的模板(typeFamily == 1)。
-----编辑------
Node
了解 Property
,因为它聚合了它们。它看起来像这样:
#include "Property.hpp" // This file also contains the declaration for PropertyBase.
class Node
{
private:
std::vector<PropertyBase*> m_props;
}
最佳答案
改用前向声明:
ConcreteNodeA.h:
class ConcreteNodeB;
class ConcreteNodeA : public Node
{
protected:
Property<ConcreteNodeB*>& m_nodeB;
};
ConcreteNodeB.h:
class ConcreteNodeA;
class ConcreteNodeB : public Node
{
protected:
Property<ConcreteNodeA*>& m_nodeA;
};
关于c++ - 模板和循环依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20730837/