提问人:Rick C. Hodgin 提问时间:6/17/2023 最后编辑:Rick C. Hodgin 更新时间:6/17/2023 访问量:92
如何在 C++ 的 #define 中引用函数原型参数默认值?
How can I reference function prototype parameter default values in a #define in C++?
问:
假设我有一个函数原型,它默认了几个参数:
bool debug_log(char* text, int len,
bool log_always = true, // Defaults to yes, log
SRgba* backRgba = NULL, // Use default color
SRgba* foreRgba = NULL); // Use default color
如果我创建了一些引用该函数,但为其日志记录类型填充了颜色值,我如何根据该参数在原型中的定义方式获得该参数的默认值?#defines
log_always
#define debug_log_err(a, b) debug_log(a, b, \
true, \
&errBackRgba, \
&errForeRgba)
#define debug_log_block(a, b) debug_log(a, b, \
true, \
&blockBackRgba, \
&blockForeRgba)
#define debug_log_highlight(a, b) debug_log(a, b, \
true, \
&highlightBackRgba, \
&highlightForeRgba)
在这些情况下,目前一切都是同步的,因为第三个参数正在传入,这是原型定义默认参数的方式。但是,如果我后来进入并决定将log_always设置为 ,那么除非我记得也更新我的 #define 用法,否则它们将过时且不同步。true
false
我想要某种方式来使用 @ 字符之类的东西来做这样的事情,它告诉编译器使用原型的任何默认值 就在那里,而不是我必须对它进行硬编码。
#define debug_log_err(a, b) debug_log(a, b, \
/* Let the compiler fill in */ @, \
&errBackRgba, \
&errForeRgba)
#define debug_log_block(a, b) debug_log(a, b, \
/* Let the compiler fill in */ @, \
&blockBackRgba, \
&blockForeRgba)
#define debug_log_highlight(a, b) debug_log(a, b, \
/* Let the compiler fill in */ @, \
&highlightBackRgba, \
&highlightForeRgba)
这样的能力存在吗?如果没有,这似乎是 C++ 中的一个缺点,类似于无法只指定几个参数,并在提供时让其余参数自动填充其默认值。
更新:我得到的是,像这样的扩展到他们扩展到的任何内容,然后进行编译。所以也许我要问的问题是......有没有办法在函数中使用干预默认参数进行引用,我知道答案是否定的。所以,这个问题主要是评论,我认为应该改变,并且应该将能力添加到 C++ 中。#define
答:
这样的能力存在吗?如果没有,这似乎是 C++ 中的一个缺点,类似于无法只指定几个参数,并在提供时让其余参数自动填充其默认值。
编译器无法猜测您提供的参数的位置,这就是为什么可选参数必须排在最后的原因。这是惯例。
当然,你的观点是添加一个运算符,让编译器知道你正在尝试替换函数原型提供的默认值,但编译器实际上不可能知道你试图调用什么函数
// the operator for argument substitution is @
int log(int level, bool flag = false, int color = 0);
int log(int level, int color = 0);
int main() {
log(0, @, 1); // Obviously, there's only one function, so this call is clear
log(0, @); // But considering overloading, this call is ambiguous
return 0;
}
因此,您可以看到操作员在哪些方面存在不足,并且在链接时可能导致微不足道的问题。
至于解决方案,为什么不直接将参数移到后面呢?log_always
bool debug_log(char* text, int len,
SRgba* backRgba = NULL, // Use default color
SRgba* foreRgba = NULL, // Use default color
bool log_always = true, // Defaults to yes, log
);
#define debug_log_err(a, b) debug_log(a, b, \
&errBackRgba, \
&errForeRgba, \
true)
#define debug_log_block(a, b) debug_log(a, b, \
&blockBackRgba, \
&blockForeRgba)
#define debug_log_highlight(a, b) debug_log(a, b, \
&highlightBackRgba, \
&highlightForeRgba)
评论
debug_log("hi", 2, NULL, NULL, false);
要解决您的问题,请将函数原型和宏替换为常量:true
const bool log_always_default = true; // Defaults to yes, log
bool debug_log(char* text, int len,
bool log_always = log_always_default,
SRgba* backRgba = NULL, // Use default color
SRgba* foreRgba = NULL); // Use default color
#define debug_log_err(a, b) debug_log(a, b, \
log_always_default, \
&errBackRgba, \
&errForeRgba)
#define debug_log_block(a, b) debug_log(a, b, \
log_always_default, \
&blockBackRgba, \
&blockForeRgba)
#define debug_log_highlight(a, b) debug_log(a, b, \
log_always_default, \
&highlightBackRgba, \
&highlightForeRgba)
现在,如果您更改为 ,它将影响您的所有宏。log_always_default
false
正如其他人指出的那样,没有理由在这里使用宏。您可以将它们替换为以下函数:inline
inline bool debug_log_err(char* text, int len)
{
return debug_log(text, len, log_always_default, &errBackRgba, &errForeRgba);
}
评论
#define debug_log_err(a, b, c) debug_log(a, b, &errBackRgba, &errForeRgba, c)