c++ - 模板和循环依赖

标签 c++ templates generic-programming

我有以下架构问题,导致 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/

相关文章:

c++ - 访问冲突读取位置0xcdcdcdcd - VS 2010 win7

c++ - 提取size_t模板参数

c++ - 非静态成员函数的无效使用 在类模板的成员函数的实例化中?

java - 如果类型是原始类型或类型是对象,请检查反射

c++ - 在 C++ 库和程序中具有相同接口(interface)的类。 exe版本是

c++ - 如何在 Eigen 中翻译矩阵(4x4)?

c++ - Objective C 对象作为 C++ 类中的实例变量

php - CodeIgniter - 在网页上创建 "block"元素的正确方法

java - 模板构造函数,并在主类中创建一个对象