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

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

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

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)

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

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

lf5gs5x2

lf5gs5x21#

要解决这个问题,请将函数原型和宏中的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);
}
yk9xbfzb

yk9xbfzb2#

有这样的能力吗?如果没有,这似乎是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)

相关问题