如何使用以前的定义重新定义宏

发布于 2024-09-06 03:00:39 字数 469 浏览 4 评论 0原文

假设我有以下宏:

#define xxx(x) printf("%s\n",x);

现在在某些文件中我想使用该宏的“增强”版本而不更改其名称。新版本探索了原始版本的功能并做了更多的工作。

#define xxx(x) do { xxx(x); yyy(x); } while(0)

这当然会给我重新定义警告,但为什么我得到“xxx”未在此范围内声明?我应该如何正确定义它?

编辑:根据此 http://gcc.gnu。 org/onlinedocs/gcc-3.3.6/cpp/Self_002dReferential-Macros.html 应该是可以的

Suppose I have the following macro:

#define xxx(x) printf("%s\n",x);

Now in certain files I want to use an "enhanced" version of this macro without changing its name. The new version explores the functionality of the original version and does some more work.

#define xxx(x) do { xxx(x); yyy(x); } while(0)

This of course gives me redefition warning but why I get 'xxx' was not declared in this scope? How should I define it properly?

EDIT: according to this http://gcc.gnu.org/onlinedocs/gcc-3.3.6/cpp/Self_002dReferential-Macros.html it should be possible

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

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

发布评论

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

评论(7

海未深 2024-09-13 03:00:39

不可能。宏可以使用其他宏,但它们使用的是扩展时可用的定义,而不是定义时的定义。 C 和 C++ 中的宏不能递归,因此新宏中的 xxx 不会扩展并被视为函数。

Not possible. Macros can use other macros but they are using the definition available at expand time, not definition time. And macros in C and C++ can't be recursive, so the xxx in your new macro isn't expanded and is considered as a function.

无戏配角 2024-09-13 03:00:39

自引用宏根本不起作用:

http:// gcc.gnu.org/onlinedocs/cpp/Self_002dReferential-Macros.html#Self_002dReferential-Macros

如果您正在使用 C++,则可以使用模板函数和命名空间获得相同的结果:

template <typename T> void xxx( x ) {
        printf( "%s\n", x );
}

namespace my_namespace {

template <typename T> void xxx( T x ) {
        ::xxx(x);
        ::yyy(x);
}

}

Self-referential macros do not work at all:

http://gcc.gnu.org/onlinedocs/cpp/Self_002dReferential-Macros.html#Self_002dReferential-Macros

If you're working on C++ you can obtain the same results with template functions and namespaces:

template <typename T> void xxx( x ) {
        printf( "%s\n", x );
}

namespace my_namespace {

template <typename T> void xxx( T x ) {
        ::xxx(x);
        ::yyy(x);
}

}
心房敞 2024-09-13 03:00:39

您将无法重用宏的旧定义,但可以取消定义并进行新定义。希望复制和粘贴不会太复杂。

#ifdef xxx
#undef xxx
#endif
#define xxx(x) printf("%s\n",x);

我的建议是定义一个 xxx2 宏。

#define xxx2(x) do { xxx(x); yyy(x); } while(0);

You won't be able to reuse the old definition of the macro, but you can undefine it and make the new definition. Hopefully it isn't too complicated to copy and paste.

#ifdef xxx
#undef xxx
#endif
#define xxx(x) printf("%s\n",x);

My recommendation is defining an xxx2 macro.

#define xxx2(x) do { xxx(x); yyy(x); } while(0);
如梦初醒的夏天 2024-09-13 03:00:39

如果我们知道“xxx”宏中“x”参数的类型,我们可以通过在函数中使用它来重新定义宏,然后将“xxx”宏定义为该函数

“xxx”宏的原始定义:

#define xxx(x) printf("xxx %s\n",x);

在某个文件中制作“xxx”宏的增强版本:

/* before redefining the "xxx" macro use it in function 
 * that will have enhanced version for "xxx" 
 */
static inline void __body_xxx(const char *x)
{
    xxx(x);
    printf("enhanced version\n");
}

#undef  xxx
#define xxx(x) __body_xxx(x)

If we know type of 'x' parameter in the 'xxx' macro, we can redefine macro by using it in a function and then define the 'xxx' macro as this function

Original definition for the 'xxx' macro:

#define xxx(x) printf("xxx %s\n",x);

In a certain file make enhanced version of the 'xxx' macro:

/* before redefining the "xxx" macro use it in function 
 * that will have enhanced version for "xxx" 
 */
static inline void __body_xxx(const char *x)
{
    xxx(x);
    printf("enhanced version\n");
}

#undef  xxx
#define xxx(x) __body_xxx(x)
牵你的手,一向走下去 2024-09-13 03:00:39

来自: https://gcc.gnu.org/onlinedocs/gcc/ Push_002fPop-Macro-Pragmas.html

#define X  1
#pragma push_macro("X")
#undef X
#define X -1
#pragma pop_macro("X")
int x [X];

From: https://gcc.gnu.org/onlinedocs/gcc/Push_002fPop-Macro-Pragmas.html

#define X  1
#pragma push_macro("X")
#undef X
#define X -1
#pragma pop_macro("X")
int x [X];
豆芽 2024-09-13 03:00:39

这不完全是您所要求的,但它可以提供帮助。

您可以在给宏定义新定义之前#undef 宏。

示例:

#ifdef xxx
#undef xxx
#endif
#define xxx(x) whatever

但我从未听说过(或见过)递归宏。我认为这是不可能的。

It is not exactly what you're asking for but it can help.

You can #undef a macro prior to giving it a new definition.

Example:

#ifdef xxx
#undef xxx
#endif
#define xxx(x) whatever

I never heard of (or seen) a recursive macro though. I don't think it is possible.

歌入人心 2024-09-13 03:00:39

这个答案并没有完全回答你的问题,但我觉得它在按照你打算使用你的方法的方式工作方面做得很好(如果可能的话)。
这个想法是让所有执行实际工作的文件特定宏具有唯一的名称(例如 LOG_GENERICLOG_SPECIFIC),并具有通用标记(在您的case xxx) 只需指向当前适当的宏。
另外,使用非标准但广泛使用的 #pragma push_macro#pragma pop_macro 我们都可以修改通用的 xxx 令牌并将其恢复为以前的版本。
例如,假设有两个头文件,generic.hppspecic.hpp,这里的公共标记是 LOG

// generic.hpp
#pragma once

#include <cstdio>

#define LOG_GENERIC(x) printf("INFO: " x "\n")
#define LOG LOG_GENERIC

void generic_fn(){LOG("generic");} // prints "INFO: generic\n"
// specific.hpp
#pragma once

#include "generic.hpp"

#define LOG_SPECIFIC(x) do {printf("<SPECIFIC> "); LOG_GENERIC(x);} while (0)

#pragma push_macro("LOG")
#undef LOG
#define LOG LOG_SPECIFIC

void specific_fn(){LOG("specific");} // prints "<SPECIFIC> INFO: specific\n"

#undef LOG
#pragma pop_macro("LOG")

通过这样做,我们得到优点:

  • 通过 #pragma push_macro#pragma pop_macro 以可恢复的方式修改 LOG 的简单机制
  • 能够引用某些< code>LOG_* 显式宏(LOG_SPECIFIC 可以使用 LOG_GENERIC
    • 我们无法在 LOG_SPECIFIC 定义中引用 LOG,我们必须遍历 LOG_GENERIC
    • 这与您的问题不同,但我个人认为这是更好的设计,否则您将能够允许 LOG_SPECIFIC 定义之上的宏影响它,听起来就像每次都做错事

链接到上面示例的 github 存储库

This answer doesn't answer your question exactly, but I feel like it does a good job at working the way you would intend to use your method (if it was possible).
The idea is for all of your file-specific macros that do actual work to have a unique name (for example LOG_GENERIC and LOG_SPECIFIC), and having the common token (in your case xxx) simply point to the currently appropriate macro.
Plus, using non-standard but widely available #pragma push_macro and #pragma pop_macro we can both modify the common xxx token and restore it to the previous version.
For example, imagine two header files, generic.hpp and specific.hpp, common token here being LOG:

// generic.hpp
#pragma once

#include <cstdio>

#define LOG_GENERIC(x) printf("INFO: " x "\n")
#define LOG LOG_GENERIC

void generic_fn(){LOG("generic");} // prints "INFO: generic\n"
// specific.hpp
#pragma once

#include "generic.hpp"

#define LOG_SPECIFIC(x) do {printf("<SPECIFIC> "); LOG_GENERIC(x);} while (0)

#pragma push_macro("LOG")
#undef LOG
#define LOG LOG_SPECIFIC

void specific_fn(){LOG("specific");} // prints "<SPECIFIC> INFO: specific\n"

#undef LOG
#pragma pop_macro("LOG")

By doing things this way we get the benefits of:

  • an easy mechanism to modify LOG in a restorable way via #pragma push_macro and #pragma pop_macro
  • being able to refer to certain LOG_* macros explicitly (LOG_SPECIFIC can use LOG_GENERIC)
    • we can't refer to LOG inside of LOG_SPECIFIC definition, we have to go through LOG_GENERIC
    • this is different to your question, but personally I am of the opinion that this is the better design, otherwise you gain the ability to allow macros above the LOG_SPECIFIC definition to affect it, just sounds like the wrong thing to do every time

Link to a github repository with the example above

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