8

如何解决以下循环依赖?

typedef boost::variant<int, bool, double, std::string, Structure> Value;
typedef std::list<std::pair<std::string, ValueContainer>> Structure;
typedef std::vector<Value> ValueContainer;

我正在尝试以更 C++ 的形式表示来自 C api 数据库库的对象。该数据库允许存储值或值数组,以及具有结构的表示,如下所示:

typedef struct ApiStructureMember 
{
    char* name;
    struct ApiValueContainer value;
    struct ApiStructureMember_T* next;
} ApiStructureMember_T;

最后用一个union来表示一个值,如下:

typedef struct ApiValue 
{
    union 
    {
        int i;
        const char*   s;
        ...
        struct ApiStructureMember_T* firstStructureMember;
    } value;
} ApiValue_T; 
4

2 回答 2

5

您不能有相互包含的类型。想一想:编译器会进入生成数据的无限循环。

有两种通用模式:第一种是通过数据类型相互指向

struct OddNode; // forward declaration

struct EvenNode 
{
    OddNode* prev;
    OddNode* next;
};

struct OddNode
{
    EvenNode* prev;
    EvenNode* next;
};

如果您放弃指针,并通过值包含实现偶数和奇数节点,那么编译器将永远无法解析定义。

一般来说:只需画出您希望如何布置数据的图片,用方框表示数据,用线连接各个部分。然后用一个类替换每个框,并用指向相应类的指针替换每一行。如果您在某处有循环依赖,只需在代码顶部前向声明类。

第二个循环依赖是通过奇怪重复的模板参数(CRTP)

template<typename T> 
struct Y 
{};

struct X
: 
    public Y<X> 
{};

您的示例将使用带有StructureasXstd::list< ..., Structure>as的 CRTP Y<X>

于 2012-08-09T14:04:40.650 回答
2

这不是一个解决方案吗?

class Structure;
typedef boost::variant<int, bool, double, std::string, Structure> Value;
typedef std::vector<Value> ValueContainer;

class Structure: public std::list<std::pair<std::string, ValueContainer>>
{
};
于 2012-08-09T14:16:19.957 回答