[英]Using a macro to define an include file
长话短说,我正在编写一些代码,这些代码需要基于各种配置选项的不同头文件。 我可以做这样的事情:
#if OPTION == A
#include "relative/path/to/file/a.hpp"
#elseif OPTION == B
#include "relative/path/to/file/b.hpp"
#elseif OPTION = ...
...
#endif
这会起作用,但对于可能不仅仅是少数文件的情况,这似乎是一个非常丑陋的解决方案。 我也可以简单地包含所有各种头文件,但这似乎也有点丑陋的解决方案,如果文件(出于某种可怕的原因)开始重新定义相同的对象,它可能会在未来造成问题。 我的想法是,像下面这样的东西会很好,特别是在其余代码是如何编写的上下文中:
#define QUOTE(str) #str
#define STRINGIFY(A,B) QUOTE(A##B)
...
#include STRINGIFY(relative/path/to/option/,OPTION)
这个问题似乎有两个方面:
OPTION
定义没有在STRINGIFY
内正确展开。STRINGIFY
完全失败,g++ 给我一个错误,如下所示:错误:粘贴“/”和“OPTION”没有给出有效的预处理令牌
我似乎找不到任何关于为什么/
是 C++ 预处理器的坏字符的真实信息,只有几篇文章说你应该把"/"
放入并依赖自动 C++ 字符串连接(这在#include
语句)。 如果我只是想做一些非常愚蠢的事情,我愿意考虑设计替代方案,但我也想弄清楚为什么这不起作用。
编辑:我应该澄清一下,我正在研究最初由一组科学家设计的代码库。 合理的编码约定和对如何使用代码的典型期望完全被排除在外。 这段代码可能至少会被修改多次,通常由那些将整个职业生涯都用于编写 Fortran 77 并认为面向对象编程是一些新奇的发明,只会让你的代码更难理解的人修改。
编写宏时,必须查看预处理后的输出。 使用gcc
就是-E
选项。
要包含不同的文件,我将依赖您的构建工具而不是宏 voodoo。 例如,当代码是
include option
然后gcc -E -option=\"foo.h\"
产生
include "foo.h"
请注意,我在这里省略了#
,否则由于找不到"foo.h"
,预处理会失败。
我想做类似的事情,四处搜索并找到了这篇文章,在尝试了一些事情之后,我想我可以帮助你。
所以,你的方法:
#define QUOTE(str) #str
#define STRINGIFY(A,B) QUOTE(A##B)
...
#include STRINGIFY(relative/path/to/option/,OPTION)
据我了解https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html不起作用,因为使用##
粘贴令牌时,结果必须是有效令牌,其中类似于path/to/file.hpp
不是有效的预处理令牌。
现在,我认为您只需要一个包含路径和要替换的令牌的宏。 好吧,如果您使用-I
标志,您实际上并不需要添加相对路径。 您的宏可能看起来像#define myMacro relative/path/to/file/OPTION.hpp
,然后您只需要定义OPTION
并将其传递给一个宏,以便OPTION
被其值替换,然后另一个宏被字符串化。 此处描述了这两个级别的宏https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html#Stringizing
以下示例将说明这两种情况(带/不带-I
标志)。
考虑这个目录结构:
.
|-- a.c
|-- headers
| |-- A.hpp
| `-- B.hpp
`-- makefile
其中交流:
#define header OPTION.hpp
#define xstr(x) #x
#define str(x) xstr(x)
#include str(header)
生成文件:
PATH_OPTION ?= headers/A
OPTION ?= A
.PHONY: all
all: a.c
cpp -D OPTION=${PATH_OPTION} $<
cpp -I./headers -D OPTION=${OPTION} $<
A.hpp
#warning Including A.hpp
1
B.hpp
#warning Including B.hpp
2
有了这个,您可以调用make
默认情况下将包含headers/A.hpp
并且您应该能够看到两种方法(带/不带-I
标志)工作并打印到标准输出相应的警告。
要包含headers/B.hpp
,您可以根据您采用的方法make OPTION=B
或make PATH_OPTION=headers/B
。
我也尝试使用g++
而不是cpp
,它也可以。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.