为什么在项目中使用#include_next?

Cod*_*aFi 49 gcc include c-preprocessor

引用包装器标题上的iOS 文档:

#include_next不区分<file>和"file"包含,也不检查您指定的文件是否与当前文件同名.它只是查找名为的文件,从找到当前文件的目录后的搜索路径中的目录开始.

使用"#include_next"会导致很大的混乱.我们建议仅在没有其他替代方案时使用.特别是,它不应该用在属于特定程序的标题中; 它应该只用于沿着fixincludes进行全局修正.

那么,有两个问题,#include_next是什么,为什么你需要使用它?

Ham*_*son 68

如果您想用自己的一个替换默认标头,则使用它,例如,假设您要替换"stdlib.h".您将在项目中创建一个名为stdlib.h的文件,该文件将包含在内,而不是默认标头.

如果要向stdlib.h添加一些内容而不是完全替换它,则使用#include_next.您创建一个名为stdlib.h的新文件,其中包含:

#include_next "stdlib.h"
int mystdlibfunc();
Run Code Online (Sandbox Code Playgroud)

而编译器将不包括你的 stdlib.h中再次递归,如将与平原的#include的情况,而是继续在其他目录名为"stdlib.h中"文件.


Cra*_*ger 9

如果你支持多个版本的东西,它会很方便.例如,我正在编写支持PostgreSQL 9.4和9.6的代码.存在许多内部API更改,主要是现有函数的新参数.

兼容头和包装函数

我可以用static inline包装函数编写兼容头文件,其中包含所有内容的新名称,基本上是一个包装器API,我在代码中的每个地方使用包装器名称.说something_compat.h:

#include "something.h"

static inline something*
get_something_compat(int thingid, bool missing_ok)
{
    assert(!missing_ok);
    return get_something(thingid);
}
Run Code Online (Sandbox Code Playgroud)

_compat到处散落或任何后缀都很难看.

包装头

相反,我可以在针对旧版本构建时在include路径中插入兼容性标头,例如compat94/something.h:

 #include_next "something.h"

 #define get_something(thingid, missing_ok) \
 ( \
     assert(!missing_ok), \
     get_something(thingid) \
 )
Run Code Online (Sandbox Code Playgroud)

所以其余的代码只能使用9.6签名.当建立9.4时,我们将前缀-Icompat94到标题搜索路径.

需要注意防止多重评估,但如果#include_next你明确使用你,请不要介意依赖gcc.在这种情况下,您还可以使用语句表达式.

当新版本是"主要"目标时,此方法很方便,但在某些有限的时间段内,需要向后兼容旧版本.因此,您逐步弃用旧版本,并尝试通过引用当前版本来保持代码清洁.

备择方案

或者是一个明智的人,使用C++,并使用重载的函数和模板内联函数:p