包含#include指令的宏定义

Bin*_*ian 34 c c++ macros c-preprocessor

有没有办法定义一个#include 在其体内包含指令的宏?

如果我只是把" #include",它给出了错误

C2162: "expected macro formal parameter"
Run Code Online (Sandbox Code Playgroud)

因为在这里我不是#用来连接字符串.
如果我使用" \# include",那么我收到以下两个错误:

error C2017: illegal escape sequence
error C2121: '#' : invalid character : possibly the result of a macro expansion
Run Code Online (Sandbox Code Playgroud)

有帮助吗?

Ben*_*mer 21

就像其他人说的那样,不,你不能在宏中包含#include语句,因为预处理器只进行一次传递.但是,你可以让预处理器基本上做同样的事情,我最近发现自己使用了一个粗糙的技巧.

意识到预处理程序指令不会在宏内部执行任何操作,但是它们会在文件中执行某些操作.因此,您可以将想要变异的代码块粘贴到文件中,将其视为宏定义(可以通过其他宏更改的片段),然后在各个位置#include此伪宏文件(make确定它没有包含警卫!).它的行为与宏不完全相同,但它可以实现一些非常类似宏的结果,因为#include基本上只是将一个文件的内容转储到另一个文件中.

例如,考虑包含许多类似命名的标题组.将它们全部写出来,或者甚至是自动生成它们都很繁琐.您可以通过执行以下操作来部分自动化其包含:

Helper宏标题:

/* 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
Run Code Online (Sandbox Code Playgroud)

伪宏文件

/* 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
Run Code Online (Sandbox Code Playgroud)

源文件

/* 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.
Run Code Online (Sandbox Code Playgroud)

这些包括甚至可能在你想要重复的代码块的中间(改变了FOO),因为Bing Jian的答案要求:包含#include指令的宏定义

我没有广泛使用这个技巧,但它完成了我的工作.它显然可以扩展为根据需要拥有尽可能多的"参数",并且您可以在那里运行您喜欢的任何预处理器命令,并生成实际代码.你不能使用它创建的东西作为另一个宏的输入,就像你可以使用普通的宏一样,因为你不能将包括在宏中.但它可以进入另一个伪宏:).

其他人可能对其他限制有一些评论,可能会出错:).

  • 听起来很棒,但理论上它没有在标准中定义,它依赖于编译器实现.请参见http://stackoverflow.com/questions/20524491/preprocessor-concatenation-for-include-path/20524959#20524959 (2认同)

Dan*_*ett 13

我不会争论它的优点,但是freetype(www.freetype.org)做了以下事情:

#include FT_FREETYPE_H
Run Code Online (Sandbox Code Playgroud)

他们在其他地方定义FT_FREETYPE_H

  • 这在标准中是明确允许的,因此只要FT_FREETYPE_H扩展为<header.h>或"header.h"形式,它就是可移植的. (8认同)

AnT*_*AnT 6

C和C++语言明确禁止因宏扩展而形成预处理程序指令.这意味着您不能将预处理程序指令包含在宏替换列表中.如果你试图通过连接(和类似的技巧)"构建"一个新的预处理器指令来欺骗预处理器,那么行为是未定义的.


Her*_*rms 5

我相信C/C++预处理器只对代码进行一次传递,所以我认为这不会起作用.您可能能够通过宏将"#include"放在代码中,但编译器会阻塞它,因为它不知道如何处理它.对于你想要做的工作,预处理器必须对文件进行第二次传递才能获取#include.


hel*_*dre -2

为什么宏需要#include?如果您要 #include 宏所在的任何文件,则可以将 #include 与所有其余 #include 语句一起放在宏上方,一切都应该很好。

我认为没有理由让宏包含任何不能仅包含在文件中的内容。