在C ++中自动排序#include依赖项

时间:2010-12-30 23:14:02

标签: c++11

我有一些源自DSL的代码,需要为C ++调用者进行翻译。我需要弄清楚如何在C ++中对#include依赖项进行排序。幸运的是,我有一些限制可以使我的任务更容易:

  1. 结果不包含模板或宏。我可以使用模板或宏来让我的生活更轻松,但DSL并没有明确生成任何需要它们的东西 - 所有预处理,代码生成都在这方面得到了解决。
  2. 结果代码根本不必是可读或可维护的 - 它将由程序生成和使用。优选地,它不会涉及任何性能损失或使优化器混淆,但如果必须,我可以活下去。
  3. 但是,我必须转换一些描述合法C ++程序的代码,但是永远无法定义,例如

    struct X {
        Y y;
        Y func();
    };
    struct Y {
        X func();
    };
    // or
    struct Y {
        void func(X x);
    };
    struct X {
        void func(Y y);
    };
    

    到目前为止,我提出了这样的想法,即我会将每个类型设置为自己的独立头,然后在实现文件中,我可以#include实现所依赖的所有类型,这不会太过难。问题是我如何能够破坏X和Y的代码,以便这是可能的。

    现在,我已经考虑过应用RVO和NRVO,并为参数做一些类似的事情。但是,是不是有些情况下他们不仅没有真正的优化,而且实际上不可能?这是用MSVC10编写的,所以我可以处理C ++ 0x在这里提供的任何其他功能。

    编辑:我编辑了我的代码,因为我略微低估了我的需求。 RVO和NRVO也无法削减这一点。

    编辑编辑:我想,如果前向声明对于函数返回值和参数就​​足够了,我可以拓扑排序数据成员的包含顺序。毕竟,做

    之类的事情仍然不合法
    struct X {
        Y y;
    };
    struct Y {
        X x;
    };
    

3 个答案:

答案 0 :(得分:1)

为什么不使用前向声明?

如果以这种方式声明X和Y,那么你的例子就完全可以了:

struct Y;
struct X {
    Y func();
};
struct Y {
    X func();
};

您可以将每个类型声明放入其自己的标头中,通过声明中使用的每种类型的前向声明进行前置,然后在实现文件中包含所有使用类型的标头。如果您转发声明类型声明中使用的每个类型,则不再需要担心首先要包含哪个文件。没关系。

总结一下:

headerA.h

#pragma once
class B;

class A {
    B b;
public:
    void myfunc();
};

headerB.h

#pragma once
class A;

class B {
    A a;
};

implA.cpp

#include "headerA.h"
#include "headerB.h"

void A::myfunc() {
    // ...
}

这种方式在不相关的代码中使用A类时,您必须同时包含headerA.hheaderB.h。如果您只想在使用类型A时包含headerA.h,请按以下方式调整标题:

headerA.h

#pragma once
class B;
#include "headerB.h"

class A {
    B b;
public:
    void myfunc();
};

headerB.h

#pragma once
class A;
#include "headerA.h"

class B {
    A a;
};

包容警卫将负责其余的工作。

答案 1 :(得分:1)

拓扑排序是要走的路。

如果这不起作用,您需要使用shared_ptr或放宽排序约束的东西来转换代码。

答案 2 :(得分:0)

按地址传递参数,或者创建一个不依赖于X或Y的中间数据类型并传递它。你真的无法避免返回/传递值问题,因为大小/接口不可用。因为它们是共同依赖的。

我想另一种选择是在同一个类接口中声明它们。

你可以使用模板和专业化......但除非你愿意编写定义,否则维护可能会很麻烦,而且生成器为此提供了一个选项。