【问题标题】:Can you use #define to change a #include?您可以使用#define 来更改#include 吗?
【发布时间】:2014-08-29 09:08:05
【问题描述】:

是否可以在预置过程中将使用 #include <foo>#include "foo" 包含的库更改为不同的库,以便充当不同的库,例如 #include <bar>?我有一个库在一个上下文中不能使用当前的 #include 语句,但在其他地方工作正常,所以我不想直接更改它。是否可以使用#define 来解决这个问题?

【问题讨论】:

  • #ifdef foo #define bar #ifndef foo #define foobar #endif
  • 是的,你可以做一个#ifdef SOMEVAR 然后#include #else #include
  • 您也可以使用#define FILENAME "something"(定义基于其他宏)后跟#include FILENAME 以包含不同的文件。

标签: c++ include c-preprocessor


【解决方案1】:

有两种方法可以做到这一点。更简单、更明显的方法:

#define INCLUDE_FOO

// ...

#ifdef INCLUDE_FOO
#include <foo>
#else
#include <bar>
#endif

还有更短但更挑剔的方式:

#define FOO_HEADER "foo"

// ...

#include FOO_HEADER

如果你使用第二种方式,你必须小心,因为 C 标准没有完全定义 #include 的行为,后面跟任何不是 "..."&lt;...&gt; 的东西。它说“任何不是......”都是完全宏扩展的,#include 行应用特殊的标记化规则(例如&lt;foo.h&gt; 是五个标记,而不是一个) 然后发生实现定义的事情。

如果完整宏扩展的结果是单个字符串文字标记,那么我所知道的所有实现都会按照您的预期进行,即他们会将其视为已编写 #include "...",其中 ... 是内容的字符串文字。 (但是,字符串文字中反斜杠的行为可能与您预期的不同。仅使用正斜杠作为目录分隔符;这在 Windows 和其他地方都可以可靠地工作。)

如果完全宏扩展的结果是其他任何东西,则行为是不可预测的,并且不仅在实现之间有所不同,而且在相同实现的点版本之间也有所不同。避免。

附录:如果#include 行以两种典型格式之一编写...

#include "foo"
#include <foo>

... 那么宏扩展不会发生并且不能被强制发生。这意味着您可能希望避免因问题而更改第三方标头。

【讨论】:

  • 这是一种有趣的做事方式。我想你可以添加一些#ifndef 逻辑让它稍微好一点,所以至少为#include 定义了一些东西。谢谢你的想法。
【解决方案2】:

基本上你可以在你的 cpp 文件中定义一个变量来切换包含文件的行为:

所以在 a.cpp 中

#define BAR
#include "myHeader.h"

在“myheader.h:”中

#ifdef BAR
#include <bar>
#else
#include <foo>
#endif

有一篇很好的 GOTW 文章介绍了使用预处理器宏来切换行为的其他方式

【讨论】:

  • 这行得通。谢谢你。只是想知道,有没有办法做到这一点而无需更改库?
  • 我不这么认为,我只是在绞尽脑汁看看你是否#undef 它我认为不是因为你正在控制头文件的行为,所以文件必须知道如何切换它需要包含的头文件
  • 我在想如果你可以#undef #include 但这是不允许的,即使它不会改变它包含的内容,所以我认为你不能在不修改标题的情况下做到这一点
猜你喜欢
  • 1970-01-01
  • 2014-01-26
  • 1970-01-01
  • 2019-03-11
  • 1970-01-01
  • 2013-01-15
  • 1970-01-01
  • 2011-08-29
  • 1970-01-01
相关资源
最近更新 更多