包含#include指令的宏定义

发布于 2024-07-08 02:48:12 字数 419 浏览 8 评论 0原文

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

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

C2162: "expected macro formal parameter"

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

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

有帮助吗?

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

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

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:

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

Any help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

放血 2024-07-15 02:48:12

所以就像其他人说的那样,不,宏中不能有 #include 语句,因为预处理器只执行一次。 但是,您可以使用我最近使用的一个粗糙技巧使预处理器执行基本相同的操作。

请注意,预处理器指令不会在宏内执行任何操作,但它们会在文件中执行某些操作。 因此,您可以将要更改的代码块粘贴到文件中,将其视为宏定义(带有可以由其他宏更改的片段),然后在各个位置 #include 这个伪宏文件(使确保它没有包含防护装置!)。 它的行为并不完全像宏,但它可以实现一些非常类似宏的结果,因为 #include 基本上只是将一个文件的内容转储到另一个文件中。

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

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.

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

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

其他人可能会对其他限制以及可能出现的问题有一些评论:)。

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.

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.

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

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 :).

梦里兽 2024-07-15 02:48:12

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

#include FT_FREETYPE_H

他们在其他地方定义 FT_FREETYPE_H

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

#include FT_FREETYPE_H

where they define FT_FREETYPE_H elsewhere

梦年海沫深 2024-07-15 02:48:12

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

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.

白龙吟 2024-07-15 02:48:12

我相信 C/C++ 预处理器只对代码进行一次传递,所以我认为这行不通。 您也许可以通过宏将“#include”放入代码中,但编译器会因它而窒息,因为它不知道如何处理它。 对于您想要执行的操作,预处理器必须对文件进行第二次传递才能获取#include。

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.

晨曦慕雪 2024-07-15 02:48:12

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

如果您在 C 或 C++ 中进行编译,某些头文件(尤其是 OpenMPI 中的 mpi.h)的工作方式会有所不同。 我正在从我的 C++ 程序链接到 C MPI 代码。 为了包含标头,我执行了通常的操作:

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

但这不起作用,因为即使在 C 链接中,__cplusplus 仍然被定义。 这意味着 blah.h 包含的 mpi.h 开始定义模板,并且编译器会终止并提示您不能使用具有 C 链接的模板。

因此,我在 blah.h 中要做的就是替换

#include <mpi.h>

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

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

如果有人能找到另一种方法来完成此任务,请告诉我。

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:

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

But this doesn't work because __cplusplus is 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.

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

#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_C which does the above for the specified file. But I guess that doesn't work.

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

美煞众生 2024-07-15 02:48:12

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

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

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

帕维尔·齐帕克

不管怎样,这次尝试背后的原因是我试图做以下事情
重复使用代码片段作为宏:

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;
    }
}

对于另一个任务,我需要有一个类似的函数,

void bar(AbstractClass object)

我将在其中放置

#include "snippets/bar.cpp"

一个类似的函数,当然它位于“snippets/foo.cpp”和“snippets/bar.cpp”中,任务特定的代码被写。

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#

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

Pawel Dziepak

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.

阳光的暖冬 2024-07-15 02:48:12

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

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

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.

A君 2024-07-15 02:48:12

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

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

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.

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

哑剧 2024-07-15 02:48:12

传染性是正确的 - 如果您正在执行:

myFile.c:

#include "standardAppDefs.h"
#myStandardIncludeMacro

standardAppDefs.h:

#define myStandardIncludeMacro #include <foo.h>

为什么不直接说:

myFile.c:

#include "standardAppDefs.h"

standardAppDefs.h:

#include <foo.h>

并忘记宏?

Contagious is right -- if you're doing:

myFile.c:

#include "standardAppDefs.h"
#myStandardIncludeMacro

standardAppDefs.h:

#define myStandardIncludeMacro #include <foo.h>

Why not just say:

myFile.c:

#include "standardAppDefs.h"

standardAppDefs.h:

#include <foo.h>

And forget the macros?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文