C++11 自动排序#在C+中包含依赖项+; 我有一些代码源于一个DSL,需要为C++调用方翻译。我需要知道如何在C++中对包含依赖项进行排序。幸运的是,我有一些限制可以使我的任务更容易: 结果不包含模板或宏。我可以使用模板或宏来简化我的生活,但是DSL并没有显式地生成任何需要它们的东西——所有的预处理、代码生成都是在这方面完成的 生成的代码根本不需要可读或可维护——它将由程序生成和使用。最好它不会涉及任何性能惩罚或混淆优化器,但如果必须的话,我可以活下去 但是,我必须转换一些描述合法C++程序但不能被定义的代码,例如 struct X { Y y; Y func(); }; struct Y { X func(); }; // or struct Y { void func(X x); }; struct X { void func(Y y); };
到目前为止,我想到了一个想法,我会让每种类型都有自己的独立头,然后在实现文件中,我可以#包括实现所依赖的所有类型,这不会太困难。问题是我怎样才能把X和Y的代码弄乱,这样才有可能 现在,我考虑应用RVO和NRVO,并对参数做一些类似的操作。但是,在有些情况下,它们不仅不是真正的优化,而且实际上是不可能的吗?这是用MSVC10编写的,因此我可以处理C++0x在这里提供的任何附加功能 编辑:我编辑了我的代码,因为我稍微低估了我的需求。RVO和NRVO也不能解决这个问题 编辑:我想,如果前向声明能够满足函数返回值和参数的要求,我可以对数据成员的include顺序进行拓扑排序。毕竟,像这样做仍然是不合法的C++11 自动排序#在C+中包含依赖项+; 我有一些代码源于一个DSL,需要为C++调用方翻译。我需要知道如何在C++中对包含依赖项进行排序。幸运的是,我有一些限制可以使我的任务更容易: 结果不包含模板或宏。我可以使用模板或宏来简化我的生活,但是DSL并没有显式地生成任何需要它们的东西——所有的预处理、代码生成都是在这方面完成的 生成的代码根本不需要可读或可维护——它将由程序生成和使用。最好它不会涉及任何性能惩罚或混淆优化器,但如果必须的话,我可以活下去 但是,我必须转换一些描述合法C++程序但不能被定义的代码,例如 struct X { Y y; Y func(); }; struct Y { X func(); }; // or struct Y { void func(X x); }; struct X { void func(Y y); };,c++11,C++11,到目前为止,我想到了一个想法,我会让每种类型都有自己的独立头,然后在实现文件中,我可以#包括实现所依赖的所有类型,这不会太困难。问题是我怎样才能把X和Y的代码弄乱,这样才有可能 现在,我考虑应用RVO和NRVO,并对参数做一些类似的操作。但是,在有些情况下,它们不仅不是真正的优化,而且实际上是不可能的吗?这是用MSVC10编写的,因此我可以处理C++0x在这里提供的任何附加功能 编辑:我编辑了我的代码,因为我稍微低估了我的需求。RVO和NRVO也不能解决这个问题 编辑:我想,如果前向声明能够满足
struct X {
Y y;
};
struct Y {
X x;
};
为什么不使用转发声明 如果您这样声明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();
};
#pragma once
class B;
#include "headerB.h"
class A {
B b;
public:
void myfunc();
};
headerB.h
#pragma once
class A;
class B {
A a;
};
#pragma once
class A;
#include "headerA.h"
class B {
A a;
};
implA.cpp
#include "headerA.h"
#include "headerB.h"
void A::myfunc() {
// ...
}
这样,在不相关的代码中使用类型A时,必须同时包含headerA.h
和headerB.h
。如果在使用类型A时只想包括headerA.h
,请按以下方式调整标题:
struct Y;
struct X {
Y func();
};
struct Y {
X func();
};
headerA.h
#pragma once
class B;
class A {
B b;
public:
void myfunc();
};
#pragma once
class B;
#include "headerB.h"
class A {
B b;
public:
void myfunc();
};
headerB.h
#pragma once
class A;
class B {
A a;
};
#pragma once
class A;
#include "headerA.h"
class B {
A a;
};
包含保护将处理其余部分。按地址传递参数,或创建一个不依赖于X或Y的中间数据类型并传递该类型。您确实无法避免返回/传递值问题,因为大小/接口不可用。事实上,它们是相互依存的 我想另一个选择是在同一个类接口中声明它们
您可以使用模板和专门化。。。但是,除非您愿意编写定义,否则维护起来可能会很麻烦,生成器为此提供了一个选项。拓扑排序是一种方法
如果这不起作用,您需要使用shared_ptr或放松排序约束的东西来转换代码。错误C2079:'X::y'使用未定义的结构'y'。不能将不完整类型当作完全定义的类型来使用,因为它们不是。您建议的两个头都会出错。@DeadMG好的,我应该提到使用这些类型的内联代码不会工作,因为编译器会这么说。如果头文件中确实有一些函数体,则必须包含所用类型的完整声明,或者将这些函数体移动到cpp文件中。@DeadMG还。。。在某些代码中使用类型A时,显然必须同时包含headerA.h和headedB.h。@Fiktik:什么,你是说“某些代码”,比如类定义?所以基本上,我所有的代码?@DeadMG我指的是实际使用定义类型的代码。我希望编辑后的答案在这一点上更加清晰。实际上,只通过值传递名称已知的类的代码是可以接受的。这是因为调用者和被调用者需要定义,因此调用定义良好,但“局外人”不需要定义,因此可以安全地忽略此类函数。