为啥要在项目中使用#include_next?

Posted

技术标签:

【中文标题】为啥要在项目中使用#include_next?【英文标题】:Why would one use #include_next in a project?为什么要在项目中使用#include_next? 【发布时间】:2012-05-02 22:24:16 【问题描述】:

引用iosDocumentation on Wrapper Headers:

#include_next 不区分 和 "file" 包含,也不检查您指定的文件是否具有相同的 名称为当前文件。它只是查找名为的文件,开始 搜索路径中的目录位于当前目录之后 文件已找到。

使用 `#include_next' 会导致很大的混乱。我们推荐 只有在没有其他选择时才使用它。特别是,它 不应在属于特定程序的标头中使用;它 应该只用于沿线进行全局更正 修复包括。

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

【问题讨论】:

ffmpeg 库中的一个例子:#ifndef FFMPEG_COMPAT_AIX_MATH_H #define FFMPEG_COMPAT_AIX_MATH_H #define class class_in_math_h_causes_problems #include_next <math.h> #undef class #endif /* FFMPEG_COMPAT_AIX_MATH_H */ 【参考方案1】:

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

#include_next 用于向 stdlib.h 添加一些东西而不是完全替换它。您创建一个名为 stdlib.h 的新文件,其中包含:

#include_next "stdlib.h"
int mystdlibfunc();

并且编译器不会再次递归地包含你的 stdlib.h,就像普通的#include 一样,而是继续在其他目录中查找名为“stdlib.h”的文件。

【讨论】:

【参考方案2】:

如果您支持某个东西的多个版本,它会很方便。例如,我正在编写支持 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);

但是将_compat 或任何后缀分散在任何地方都很难看。

包装头

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

 #include_next "something.h"

 #define get_something(thingid, missing_ok) \
 ( \
     assert(!missing_ok), \
     get_something(thingid) \
 )

所以其余的代码可以只使用 9.6 签名。在针对 9.4 构建时,我们会将 -Icompat94 前缀到标题搜索路径。

需要注意防止多次评估,但如果您使用#include_next,您显然不介意依赖 gcc。在这种情况下,您也可以使用statement expressions。

当新版本是“主要”目标时,这种方法很方便,但在有限的时间段内需要旧版本的向后兼容性。因此,您将逐步弃用旧版本,并尝试参考当前版本保持代码整洁。

替代方案

或者做个懂事的人,用C++,用重载函数和模板内联函数:p

【讨论】:

【参考方案3】:

include_next 用作预处理器指令,告诉编译器从解析到此头文件中排除直到并包括文件名 file.h 的搜索路径。典型的需要是当需要使用两个同名的头文件时。谨慎使用此类功能,仅在绝对必要时使用。

例如:

源 file.c 内容与路径 1 中的通常 file.h:
#include <file.h>
 int main() 
     printf("out value: %d", out_val);
     exit 0;
     
路径 1 中的 file.h 头文件包含路径 2 中的 file.h 内容: include_next 指示路径 1 子目录不用作 file.h 的搜索路径,而是使用路径 2 子目录作为搜索路径。这样,您可以拥有 2 个同名文件,而不必担心调用对自身的循环引用。
# include_next <file.h>
int out_val = UINT_MAX - INT_MAX;
路径 2 内容中的 file.h
#define INT_MAX 1<<63 - 1
#define UINT_MAX 1<<64 - 1

【讨论】:

以上是关于为啥要在项目中使用#include_next?的主要内容,如果未能解决你的问题,请参考以下文章

为啥要在每个项目包配置之后包含(CPack)?

SWIG 不支持 include_next GNU 指令

为啥要在全局和本地都安装 gulp?

eclipse 一个项目中 要建4个包,为啥建的包不是在同一目录(src)下。。而是要在Libraries下。。

为啥要在 didFinishLaunchingWithOptions 中使用 UIApplicationLaunchOptionsRemoteNotificationKey?

为啥要在hibernate中使用关联?