所以就像其他人说的那样,不,宏中不能有 #include 语句,因为预处理器只执行一次。但是,您可以使用我最近使用的一个粗糙技巧使预处理器执行基本相同的操作。
请注意,预处理器指令不会在宏内执行任何操作,但它们会在文件中执行某些操作。因此,您可以将要更改的代码块粘贴到文件中,将其视为宏定义(具有可以由其他宏更改的片段),然后在各个位置 #include 这个伪宏文件(使确保它没有包含防护装置!)。它的行为并不完全像宏,但它可以实现一些非常类似宏的结果,因为 #include 基本上只是将一个文件的内容转储到另一个文件中。
例如,考虑包含大量成组的类似名称的标头。将它们全部写出来是很乏味的,或者甚至它们可能是自动生成的。您可以通过执行以下操作部分自动化它们的包含:
辅助宏标题:
/* tools.hpp */
#ifndef __TOOLS_HPP__
#def __TOOLS_HPP__
// Macro for adding quotes
#define STRINGIFY(X) STRINGIFY2(X)
#define STRINGIFY2(X) #X
// Macros for concatenating tokens
#define CAT(X,Y) CAT2(X,Y)
#define CAT2(X,Y) X##Y
#define CAT_2 CAT
#define CAT_3(X,Y,Z) CAT(X,CAT(Y,Z))
#define CAT_4(A,X,Y,Z) CAT(A,CAT_3(X,Y,Z))
// etc...
#endif
伪宏文件
/* pseudomacro.hpp */
#include "tools.hpp"
// NO INCLUDE GUARD ON PURPOSE
// Note especially FOO, which we can #define before #include-ing this file,
// in order to alter which files it will in turn #include.
// FOO fulfils the role of "parameter" in this pseudo-macro.
#define INCLUDE_FILE(HEAD,TAIL) STRINGIFY( CAT_3(HEAD,FOO,TAIL) )
#include INCLUDE_FILE(head1,tail1.hpp) // expands to #head1FOOtail1.hpp
#include INCLUDE_FILE(head2,tail2.hpp)
#include INCLUDE_FILE(head3,tail3.hpp)
#include INCLUDE_FILE(head4,tail4.hpp)
// etc..
#undef INCLUDE_FILE
源文件
/* mainfile.cpp */
// Here we automate the including of groups of similarly named files
#define FOO _groupA_
#include "pseudomacro.hpp"
// "expands" to:
// #include "head1_groupA_tail1.hpp"
// #include "head2_groupA_tail2.hpp"
// #include "head3_groupA_tail3.hpp"
// #include "head4_groupA_tail4.hpp"
#undef FOO
#define FOO _groupB_
#include "pseudomacro.hpp"
// "expands" to:
// #include "head1_groupB_tail1.hpp"
// #include "head2_groupB_tail2.hpp"
// #include "head3_groupB_tail3.hpp"
// #include "head4_groupB_tail4.hpp"
#undef FOO
#define FOO _groupC_
#include "pseudomacro.hpp"
#undef FOO
// etc.
这些包含甚至可能位于您想要重复的代码块的中间(更改了 FOO),正如 Bingjian 的回答所要求的那样:包含#include指令的宏定义 https://stackoverflow.com/questions/266501/macro-definition-containing-include-directive/266647#266647
我没有广泛使用这个技巧,但它可以完成我的工作。显然,它可以根据需要扩展为具有尽可能多的“参数”,并且您可以在其中运行您喜欢的任何预处理器命令,并生成实际代码。您只是不能使用它创建的内容作为另一个宏的输入,就像使用普通宏一样,因为您不能将包含内容粘贴到宏中。但它可以进入另一个伪宏内部:)。
其他人可能会对其他限制以及可能出现的问题有一些评论:)。