所以就像其他人说的那样,不,你不能在宏中包含#include 语句,因为预处理器只执行一次。但是,您可以使用我最近发现自己使用的一个技巧,让预处理器基本上做同样的事情。
意识到预处理器指令不会在宏中做任何事情,但是它们会在文件中做一些事情。因此,您可以将要变异的代码块粘贴到文件中,将其视为宏定义(可以由其他宏更改的部分),然后在各个位置#include 这个伪宏文件(make确保它没有包括警卫!)。它的行为与宏不完全一样,但它可以实现一些非常类似于宏的结果,因为#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),正如 Bing Jian 要求的答案:包含 #include 指令的宏定义
我没有广泛使用这个技巧,但它可以完成我的工作。它显然可以根据需要扩展为具有尽可能多的“参数”,并且您可以在其中运行您喜欢的任何预处理器命令,并生成实际代码。您不能将它创建的内容用作另一个宏的输入,就像使用普通宏一样,因为您不能将包含内容粘贴在宏中。但它可以进入另一个伪宏:)。
其他人可能会对其他限制有一些评论,以及可能出什么问题:)。