如何重构以下C ++代码?我在我的程序中使用C ++ 11
void f(int a, int b, int c, int d, int e, int f) {
// MAX1..MAX6 are constants, N1..N6 are constants
if( a > MAX1) {
.. code block 1..
}
else if(b > MAX2) {
.. code block 2..
}
else if(c > MAX3) {
.. code block ..
}
else if(d > MAX4) {
.. code block 3 ..
}
else if(e > MAX5) {
.. code block 4 ..
}
else if(f > MAX6) {
.. code block5 ..
}
else if(( a > N1) && ( b > N2)) {
.. code block 6 ..
}
else if(( c > N3) && ( d > N4)) {
.. code block 7 ..
}
else if (( e > N5) && ( f > N6)) {
.. code block 8 ..
}
else if (( a > N1) && ( b > N2) && (d > N4)) {
.. code block 9 ..
}
else if (..some combination of (a > N1) to (f > N6)...) {
// there are more than 30 such combinations in my code
.. code block XX ..
}
else {
.... code block ....
}
答案 0 :(得分:0)
你所拥有的东西似乎并不合理,但如果你真的想重构,你可以创建一个枚举
枚举类CaseSelect {CASE0,CASE1,CASE2};
然后创建一个与当前if树非常相似的函数,每个代码块返回相应的枚举。
然后使用枚举创建一个case语句,每个
中都有相应的逻辑它不会给你带来太大的好处,但它将选择状态的逻辑与操作逻辑分开,这对于多行语句的情况可能是有益的
答案 1 :(得分:0)
您当然可以首先将a
引导至f
,MAX
和N
放入数组(这只是一个我可以展开的草图,其中包含有关您的条件的更多信息,代码块和用途):
const int MAX[6] = { ... };
const int N[6] = { ... };
const std::function funcs[6];
void f(int in[6])
{
for(int i = 0; i < 6; ++i)
{
if(in[i] > MAX[i])
{
funcs[i]();
break;
}
}
}
答案 2 :(得分:0)
所以假设你有一个离散数N的互斥整数范围(xi到yi),你想根据给定输入z的范围调用一些代码块,然后:
std::map
二叉树来存储每个范围的起点和相应的lambda。std::lower_bound
以查找候选范围与O(n)相比,这将给出大的if-else链的O(log(N))时间。
答案 3 :(得分:0)
函数中最多有64个代码块,每个代码块可以使用匿名函数或命名函数:
my_func_array[64] = {
[CONDITION(1,0,0,0,0,0)] = { codeblock1 },
[CONDITION(0,1,0,0,0,0)] = { codeblock2 },
...
};
宏将基本上将6个第一个输入连接到索引,实质上转换为:
my_func_array[64] = {
[32] = { ... },
[16] = { ... },
};
意味着您不必以任何特定顺序输入条件......
运行时,您还必须评估所有条件:
int condition = CONDITION(a < MAX1, b < MAX2, c < MAX2, ...);
if (my_func_array[condition])
my_func_array[condition]();
else
{
// this second block should cover all the other cases
int condition2 = CONDITION(a < N1, b < N2, c < N3, ... );
if (my_func_array2[condition2])
my_func_array2[condition2]();
}
答案 4 :(得分:0)
首先,我会删除前6个分支Mark B建议但
而不是break
我会return
,
我只是使用函数指针,std::function
是一种矫枉过正
这里,
我会使用std::array
并绑定检查而不是原始数组。
既然枯燥的情况已经消失,我会将相同的模式应用于剩余的分支,但这需要一些技巧,因为这些条件是复合材料。
我假设MAX1 > N1
。我希望这是真的。
首先,我将构建一个十进制数,编码所有参数:
int arg=10^5*(a>N1?1:0)+10^4*(b>N2?1:0)+10^3*(c>N3?1:0)+10^2*(d>N4?1:0)+10*(e>N5?1:0)+(f>N1?1:0)
我也会以类似的方式编码条件。例如:条件(a > N1) && ( b > N2)
变为arg >= 110000
等等。
如您所见,在此编码之后,您可以以与前6个分支相同的方式消除剩余分支。
如果效率是一个主要问题,你可以用2的幂(位移,然后使用位掩码)做同样的技巧。我没有做点小提琴,所以我无法帮助你,但它的工作方式相同,效率更高。可能和你现在拥有的if-else if链一样高效,或者更高效,因为你没有重复相同的比较。
希望这有帮助。
答案 5 :(得分:-1)
如果有很多规则,那么函数对象(例如:lambdas)可以用于救援:
我为了示范目的简化了一点,只有3个参数......
我认为非检查有一个安全的价值,在这种情况下,0
(没有它可以生存,但那样看起来会更加丑陋)。
#include <iostream>
#include <functional>
struct Rule {
int a;
int b;
int c;
std::function<int()> fun;
};
Rule rules[]{
{ 10, 0, 0, []() { std::cout << "First!"; return 0;} },
{ 0, 20, 0, []() { std::cout << "Second!"; return 1;} }
};
int f(int a, int b, int c) {
for (Rule rule : rules) {
if ((rule.a == 0 || a > rule.a)
&& (rule.b == 0 || b > rule.b)
&& (rule.c == 0 || c > rule.c))
return rule.fun();
}
std::cout << "Not match!";
return 2;
}
int main() {
f(5, 23, 3);
};