【问题标题】:To not pass an argument due to a condition由于条件不传递参数
【发布时间】:2024-04-16 22:55:02
【问题描述】:

我有这个函数声明:

void do_somthing(int a,int b,foo bar = foo());

我想为一些参数调用它,如下所示:

foo bar = get_bar_by_some_algorithm();
int a = 5,b = 6;
if(bar.empty()){
    do_somthing(a,b);
}
else{
    do_somthing(a,b,bar);
}

我想摆脱if 声明。所以,我是这样做的:

foo bar = get_bar_by_some_algorithm();
int a = 5,b = 6;
do_somthing(a,b,bar.empty()?foo():bar);

但是,如果do_somthing 从默认参数的角度来看是稳定的,但如果它更改为类似这样的内容,我的方法是可以接受的(它甚至好吗?):

void do_somthing(int a,int b,foo bar = get_special_foo());

我的代码将会过时,因为foo() 也不等于get_special_foo()

问题是我如何使用? 运算符或任何简短的等效项来在非空的情况下传递参数,而在空的情况下不传递任何东西?

说明示例(虚构语法):

do_somthing(a,b,bar.empty()? the_default_argument : bar);

【问题讨论】:

  • 三元运算符和if 都会做一个分支,顺便说一句。
  • 您只需传入bar 并执行if(bar.empty()) 签入do_somthing

标签: c++ c++11 ternary-operator default-arguments


【解决方案1】:

您使用三元运算符的方法还可以,但似乎没有必要。以后不考虑后果就为函数添加新的默认值是不正常的。如果您的默认值没有意义,那么您的设计首先就有问题。

但为了娱乐您,这里有一个无分支版本。如果我的主要担忧是由于分支预测错误导致的测量瓶颈,我可能会考虑这样的事情。我通常不会这样做,因为它不如简单的 if-statement 清晰:

static auto do_something[2] = {
    +[]( int a, int b, foo bar ) { do_something( a, b, bar ); },
    +[]( int a, int b, foo bar ) { do_something( a, b ); }
};
do_something[bar.empty()]( a, b, bar );

【讨论】:

  • 你将分支预测换成跳跃预测。
  • 不,因为编译器应该将 lambda 省略为纯函数调用,这无论如何都会发生。无论如何,这只是一个例证。
【解决方案2】:

简短的回答是您不能为此使用?:

?: 三元运算符的规范要求所有三个操作数都是有效的表达式。有效的表达式(过于简单化)是一种结构,它计算一个或多个值,(可选地)使用运算符对这些值进行操作,并产生一个结果。

其中没有任何内容的表达式是矛盾的:它不计算任何内容,因此不能是 ?: 运算符的操作数。

注意:可以有一个空语句(例如,通过一个孤立的;)。但空语句不是表达式。

隐藏if() 的明显解决方案是在函数内部进行测试,如 CompuChip 的 cmets 中所述。或者编写一个包装器函数来为您进行测试(并确保您的do_somthing() 没有在任何其他编译单元中声明,以避免直接调用它而不是包装器的诱惑)。

【讨论】: