【问题标题】:Can I use token-pasting and/or stringizing for #includes?我可以对#includes 使用令牌粘贴和/或字符串化吗?
【发布时间】:2016-02-11 18:02:17
【问题描述】:

假设我有几个文件,它们的名称都相似:Foo1Bar.hFoo2Bar.hFoo3Bar.h 等。现在,我想将这些文件自动包含在一些 main.c 中“外挂”的风格,也就是不想每个都记得#include。是否可以通过令牌粘贴来做到这一点?到目前为止,我有:

// this is the only line I want to have to change if I add Foo4Bar.h
#define FOR_EACH_FOOBAR(T) T(1)T(2)T(3)
//... somewhere else in my code
#define RUN_SOME_FUNC(T) Foo##T##Bar().run();

以上工作正常(当然假设我所有的Foo*Bar.h 文件都有类Foo*Bar 和公共run() 方法。(如果不清楚,我的例子是C++,但我不知道) t 认为问题本身(#include)是特定于 C++ 的)。

我无法弄清楚我是否也可以用我的#include 语句来做到这一点。而不是

#include <Foo1Bar.h>
#include <Foo2Bar.h>
#include <Foo3Bar.h>
#include <Foo4Bar.h>

(对我而言)更改以下内容会更好:

FOR_EACH_FOOBAR(T) T(1)T(2)T(3)T(4)
FOR_EACH_FOOBAR(INCLUDE)

我试过了:

#define INCLUDE(T) #include <Foo##T##Bar.h>

但得到错误:'#' is not followed by a macro parameter,因为它正在尝试对开始部分进行字符串化。我尝试过的任何卷积或回转都导致了相同(或类似)的错误,我不知道如何逃避#include 或其他任何方法来使其正常工作。

有可能吗?如果有,怎么做?如果没有,是否有确切的原因?

【问题讨论】:

  • 我知道这一点,我也去过那里。那时人们希望拥有类似 Lisp 的宏 :) 我想与其尝试“在”源文件中执行此操作,不如在构建过程中添加一个步骤来生成包含所有这些内容的 AllFooBars.h 标头。
  • @DanielJour 哦,好点,我没有考虑源文件之外的任何内容,但这听起来很合理。感谢您的想法 - 无论是否可以在 C 中完成,构建可能都是要走的路。
  • 底线是:不允许使用预处理器宏扩展来生成预处理器指令。所以,你不能生成#include 指令。使用#include,可以通过宏指定文件名,但这就是你所能做的。

标签: c include c-preprocessor stringification


【解决方案1】:

不是你想要的,因为# 命令由预处理器处理,并且看起来不太看是否另一个# 命令是由扩展产生的,但是有一些“生成”#include 行的功能,它们只是在 #include 文本本身之后出现...

https://gcc.gnu.org/onlinedocs/cpp/Computed-Includes.html

在此处搜索“#include 其他任何内容”:https://www.slac.stanford.edu/comp/unix/gnu-info/cpp_1.html

【讨论】:

  • 一个值得注意的星号是微软有一个扩展允许#pragma作为宏扩展的结果发出,但这与OP无关。
  • 这部分:“它看不到另一个 # 命令是否由扩展产生”是我一直在寻找的答案(尽管不希望) - 这解释了为什么没有我有任何可能的方式让#define FOR_EACH...#includes 工作(这很好,至少现在我知道)。
【解决方案2】:

你不能使用:

#define INCLUDE(T) #include Foo##T##Bar.h

因为# 被用作运算符来对参数进行字符串化。

#define STR(x) #x

char const* s = STR(THIS);

与使用相同:

char const* s = "THIS";

鉴于此,

#define INCLUDE(T) #include Foo##T##Bar.h

遇到include不是宏的参数之一的问题。因此,使用#include 是不合法的。

更新

我认为标准的 C 预处理器功能不能用于完成您希望完成的任务。个人比较喜欢看

#include <Foo1Bar.h>
#include <Foo2Bar.h>
#include <Foo3Bar.h>
#include <Foo4Bar.h>

在我的文件中比

FOR_EACH_FOOBAR(T) T(1)T(2)T(3)T(4)
FOR_EACH_FOOBAR(INCLUDE)

【讨论】:

  • 对,根据我在尝试编译时收到的错误,我知道这一点。我的问题是:有没有办法解决这个问题?我对令牌粘贴和字符串化不是很熟悉/不习惯,所以我想知道是否需要更聪明的解决方法。
  • @dwanderson,您能否在您的帖子中添加几行说明您希望如何使用此宏以及添加 Foo4Bar.h 后它将如何让您的生活变得更简单?
  • 我同意所示示例。另一方面,我更愿意看到#include QLIB_HEADERS("qlib.h") 之类的东西,而不是#include "../../qlib/headers/qlib.h"#include "qlib.h" // Hope an include path manages to find the right thing
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-29
  • 2016-05-10
  • 2014-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多