如何在C++中的#define中引用函数原型参数的默认值?

yfwxisqw  于 2023-06-25  发布在  其他
关注(0)|答案(2)|浏览(193)

假设我有一个函数原型,它默认了几个参数:

  1. bool debug_log(char* text, int len,
  2. bool log_always = true, // Defaults to yes, log
  3. SRgba* backRgba = NULL, // Use default color
  4. SRgba* foreRgba = NULL); // Use default color

如果我创建了几个引用该函数的#defines,但是填充了它们的日志类型的颜色值,我如何根据原型中的定义来获得log_always参数的默认值?

  1. #define debug_log_err(a, b) debug_log(a, b, \
  2. true, \
  3. &errBackRgba, \
  4. &errForeRgba)
  5. #define debug_log_block(a, b) debug_log(a, b, \
  6. true, \
  7. &blockBackRgba, \
  8. &blockForeRgba)
  9. #define debug_log_highlight(a, b) debug_log(a, b, \
  10. true, \
  11. &highlightBackRgba, \
  12. &highlightForeRgba)

在这些情况下,目前一切都同步,因为第三个参数传入true,这是原型定义默认参数的方式。但是如果我稍后决定将log_always设置为false,那么除非我记得也更新我的#define用法,否则它们将过时并且不同步。
我想用一些类似于@字符的东西来做这样的事情,它告诉编译器使用原型的默认值,而不是我必须硬编码它。

  1. #define debug_log_err(a, b) debug_log(a, b, \
  2. /* Let the compiler fill in */ @, \
  3. &errBackRgba, \
  4. &errForeRgba)
  5. #define debug_log_block(a, b) debug_log(a, b, \
  6. /* Let the compiler fill in */ @, \
  7. &blockBackRgba, \
  8. &blockForeRgba)
  9. #define debug_log_highlight(a, b) debug_log(a, b, \
  10. /* Let the compiler fill in */ @, \
  11. &highlightBackRgba, \
  12. &highlightForeRgba)

有这样的能力吗?如果没有,这似乎是C的一个缺点,类似于不能只指定几个参数,让其余的都在提供时自动填充默认值。
更新:我得到的是,像这样的#define扩展到它们扩展到的任何对象,然后编译。所以我想问的问题是...有没有一种方法可以在函数中使用介入的默认参数进行引用,我知道答案是否定的。所以,这个问题主要是评论,我认为应该改变,应该将能力添加到C
中。

lf5gs5x2

lf5gs5x21#

要解决这个问题,请将函数原型和宏中的true替换为常量:

  1. const bool log_always_default = true; // Defaults to yes, log
  2. bool debug_log(char* text, int len,
  3. bool log_always = log_always_default,
  4. SRgba* backRgba = NULL, // Use default color
  5. SRgba* foreRgba = NULL); // Use default color
  6. #define debug_log_err(a, b) debug_log(a, b, \
  7. log_always_default, \
  8. &errBackRgba, \
  9. &errForeRgba)
  10. #define debug_log_block(a, b) debug_log(a, b, \
  11. log_always_default, \
  12. &blockBackRgba, \
  13. &blockForeRgba)
  14. #define debug_log_highlight(a, b) debug_log(a, b, \
  15. log_always_default, \
  16. &highlightBackRgba, \
  17. &highlightForeRgba)

现在,如果您将log_always_default更改为false,它将影响所有宏。
正如其他人指出的,这里没有理由使用宏。您可以使用inline函数替换它们,例如:

  1. inline bool debug_log_err(char* text, int len)
  2. {
  3. return debug_log(text, len, log_always_default, &errBackRgba, &errForeRgba);
  4. }
展开查看全部
yk9xbfzb

yk9xbfzb2#

有这样的能力吗?如果没有,这似乎是C++的一个缺点,类似于不能只指定几个参数,让其余的都在提供时自动填充默认值。
编译器无法猜测您提供的参数的位置,这就是为什么可选参数必须放在最后的原因。这是惯例。
当然,你的目的是添加一个操作符,让编译器知道你正在尝试替代函数原型提供的默认值,但是编译器不可能真正知道你正在尝试调用什么函数

  1. // the operator for argument substitution is @
  2. int log(int level, bool flag = false, int color = 0);
  3. int log(int level, int color = 0);
  4. int main() {
  5. log(0, @, 1); // Obviously, there's only one function, so this call is clear
  6. log(0, @); // But considering overloading, this call is ambiguous
  7. return 0;
  8. }

因此,您可以看到操作符在哪里短,可能导致链接时的琐碎问题。
至于解决方案,为什么不把log_always移到参数后面呢?

  1. bool debug_log(char* text, int len,
  2. SRgba* backRgba = NULL, // Use default color
  3. SRgba* foreRgba = NULL, // Use default color
  4. bool log_always = true, // Defaults to yes, log
  5. );
  6. #define debug_log_err(a, b) debug_log(a, b, \
  7. &errBackRgba, \
  8. &errForeRgba, \
  9. true)
  10. #define debug_log_block(a, b) debug_log(a, b, \
  11. &blockBackRgba, \
  12. &blockForeRgba)
  13. #define debug_log_highlight(a, b) debug_log(a, b, \
  14. &highlightBackRgba, \
  15. &highlightForeRgba)
展开查看全部

相关问题