C++ 包含#include 指令的宏定义

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/266501/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:09:45  来源:igfitidea点击:

macro definition containing #include directive

c++cmacrosc-preprocessor

提问by Bing Jian

Is there a way to define a macro that contains a #includedirective in its body?

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

If I just put the "#include", it gives the error

如果我只是把“ #include”,它会给出错误

C2162: "expected macro formal parameter"

since here I am not using #to concatenate strings.
If I use "\# include", then I receive the following two errors:

因为在这里我不使用#连接字符串。
如果我使用“ \# include”,则会收到以下两个错误:

error C2017: illegal escape sequence
error C2121: '#' : invalid character : possibly the result of a macro expansion

Any help?

有什么帮助吗?

回答by Ben Farmer

So like the others say, no, you can't have #include statements inside a macro, since the preprocessor only does one pass. However, you can make the preprocessor do basically the same thing with a gnarly trick I found myself using recently.

所以就像其他人说的,不,你不能在宏中包含 #include 语句,因为预处理器只执行一次。但是,您可以使用我最近发现自己使用的一个棘手的技巧使预处理器做基本上相同的事情。

Realise that preprocessor directives won't do anything inside a macro, however they WILL do something in a file. So, you can stick a block of code you want to mutate into a file, thinking of it like a macro definition (with pieces that can be altered by other macros), and then #include this pseudo-macro file in various places (make sure it has no include guards!). It doesn't behave exactly like a macro would, but it can achieve some pretty macro-like results, since #include basically just dumps the contents of one file into another.

意识到预处理器指令不会在宏内部做任何事情,但是它们会在文件中做一些事情。所以,你可以把你想改变的代码块粘贴到一个文件中,把它想象成一个宏定义(可以被其他宏改变的部分),然后在不同的地方#include这个伪宏文件(make确定它没有包括守卫!)。它的行为不像宏,但它可以实现一些非常类似于宏的结果,因为#include 基本上只是将一个文件的内容转储到另一个文件中。

For example, consider including lots of similarly named headers that come in groups. It is tedious to write them all out, or perhaps even they are auto-generated. You can partially automate their inclusion by doing something like this:

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

Helper macros header:

辅助宏标头:

/* 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

Pseudo-macro file

伪宏文件

/* 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

Source 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.

These includes could even be in the middle of codes blocks you want to repeat (with FOO altered), as the answer by Bing Jian requests: macro definition containing #include directive

这些包含甚至可能位于您想要重复的代码块的中间(改变了 FOO),正如 Bing Jian 要求的答案:包含 #include 指令的宏定义

I haven't used this trick extensively, but it gets my job done. It can obviously be extended to have as many "parameters" as needed, and you can run whatever preprocessor commands you like in there, plus generate actual code. You just can't use the stuff it creates as the input into another macro, like you can with normal macros, since you can't stick the include inside a macro. But it can go inside another pseudo-macro :).

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

Others might have some comments on other limitations, and what could go wrong :).

其他人可能对其他限制有一些评论,以及可能出什么问题:)。

回答by Dan Hewett

I will not argue the merits for it, but freetype (www.freetype.org) does the following:

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

#include FT_FREETYPE_H

where they define FT_FREETYPE_H elsewhere

他们在别处定义 FT_FREETYPE_H

回答by AnT

C and C++ languages explicitly prohibit forming preprocessor directives as the result of macro expansion. This means that you can't include a preprocessor directive into a macro replacement list. And if you try to trick the preprocessor by "building" a new preprocessor directive through concatenation (and tricks like that), the behavior is undefined.

C 和 C++ 语言明确禁止作为宏扩展的结果形成预处理器指令。这意味着您不能将预处理器指令包含到宏替换列表中。如果您试图通过串联(以及类似的技巧)“构建”一个新的预处理器指令来欺骗预处理器,则行为是未定义的。

回答by Herms

I believe the C/C++ preprocessor only does a single pass over the code, so I don't think that would work. You might be able to get a "#include" to be placed in the code by the macro, but the compiler would choke on it, since it doesn't know what to do with that. For what you're trying to do to work the preprocessor would have to do a second pass over the file in order to pick up the #include.

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

回答by Lutorm

I also wanted to do this, and here's the reason:

我也想这样做,原因如下:

Some header files (notably mpi.h in OpenMPI) work differently if you are compiling in C or C++. I'm linking to a C MPI code from my C++ program. To include the header, I do the usual:

如果您使用 C 或 C++ 进行编译,某些头文件(特别是 OpenMPI 中的 mpi.h)的工作方式会有所不同。我正在从我的 C++ 程序链接到 C MPI 代码。要包含标题,我通常会这样做:

extern "C" {
#include "blah.h"
}

But this doesn't work because __cplusplusis still defined even in C linkage. That means mpi.h, which is included by blah.h, starts defining templates and the compiler dies saying you can't use templates with C linkage.

但这不起作用,因为__cplusplus即使在 C 链接中仍然定义。这意味着 blah.h 中包含的 mpi.h 开始定义模板,编译器死了,说您不能使用带有 C 链接的模板。

Hence, what I have to do in blah.h is to replace

因此,我必须在 blah.h 中做的是替换

#include <mpi.h>

with

#ifdef __cplusplus
#undef __cplusplus
#include <mpi.h>
#define __cplusplus
#else
#include <mpi.h>
#endif

Remarkably it's not just mpi.h that does this pathological thing. Hence, I want to define a macro INCLUDE_AS_Cwhich does the above for the specified file. But I guess that doesn't work.

值得注意的是,不仅仅是 mpi.h 做了这种病态的事情。因此,我想定义一个INCLUDE_AS_C对指定文件执行上述操作的宏。但我想这行不通。

If anyone can figure out another way of accomplishing this, please let me know.

如果有人能想出另一种方法来实现这一点,请告诉我。

回答by Bing Jian

I think you are all right in that this task seems impossible as I also got from

我认为你没问题,因为这个任务似乎是不可能的,因为我也是从

http://groups.google.com/group/comp.lang.c++/browse_thread/thread/03d20d234539a85c#

http://groups.google.com/group/comp.lang.c++/browse_thread/thread/03d20d234539a85c#

No, preprocessor directives in C++ (and C) are not reflective.

Pawel Dziepak

不,C++(和C)中的预处理器指令不是反射性的。

帕维尔·齐帕克

Anyway, the reason behind this attempt is that I am trying to make the following repeatedly used code snippet as a macro:

无论如何,这次尝试背后的原因是我试图将以下重复使用的代码片段作为宏:

void foo(AbstractClass object)
{
    switch (object.data_type())
    {
    case AbstractClass::TYPE_UCHAR :
        {
        typedef unsigned char PixelType;
        #include "snippets/foo.cpp"
        }
        break;
    case AbstractClass::TYPE_UINT:
        {
        typedef unsigned int PixelType;
        #include "snippets/foo.cpp"
        }
        break;
    default:
        break;
    }
}

For another task, I need to have a similar function

对于另一项任务,我需要有一个类似的功能

void bar(AbstractClass object)

where I will place

我将放在哪里

#include "snippets/bar.cpp"

and of course it is in "snippets/foo.cpp" and "snippets/bar.cpp" that the task-specific code is written.

当然,特定于任务的代码是在“snippets/foo.cpp”和“snippets/bar.cpp”中编写的。

回答by helloandre

Why would the macro need to have an #include? if you're #include'ing whatever file the macro is in, you could just put the #include above the macro with all the rest of the #include statements, and everything should be nice and dandy.

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

I see no reason to have the macro include anything that couldn't just be included in the file.

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

回答by user21714

I have no idea what you are actually trying to do but it looks like what you might want is a templated function.

我不知道您实际上想要做什么,但看起来您可能想要的是模板化函数。

That way the PixelType is just a template parameter to the block of code.

这样 PixelType 只是代码块的模板参数。

回答by HanClinto

Contagious is right -- if you're doing:

传染性是对的——如果你在做:

myFile.c:

我的文件.c:

#include "standardAppDefs.h"
#myStandardIncludeMacro

standardAppDefs.h:

标准AppDefs.h:

#define myStandardIncludeMacro #include <foo.h>

Why not just say:

为什么不直接说:

myFile.c:

我的文件.c:

#include "standardAppDefs.h"

standardAppDefs.h:

标准AppDefs.h:

#include <foo.h>

And forget the macros?

忘记宏?