if 场景的 C++ 代码重构

C++ code refactoring for if scenario

我正在寻求针对 if 条件重构 C++ 代码,这将减少代码行数并且它应该具有最小的复杂性。

示例如下:

if (xyz->a != cmd->aa)
{
   xyz->a = cmd->aa;
   obj->isFound = true;  //common code for all ifs
}


if (xyz->b != cmd->bb)
{
    xyz->b = cmd->bb;
    obj->isFound = true; 
}

以此类推..这里a,b,aa,bb被定义为一个struct元素

另一个具有数组 if 条件的示例:

 if (abc->r16[0] != cmd->r0m)
    {
        abc>r16[0] = cmd->r0m;
        obj->isFound = true; //some common code for all ifs
    }


if (abc->r16[1] != cmd->r1m)
        {
            abc>r16[1] = cmd->r1m;
            obj->isFound = true; //some common code for all ifs
        }

r16[0] 到 r16[15] 以此类推。这里 r16[15] 定义在 struct.

内部

最后一个场景是针对多维数组的 if 条件:

     if (pqr->c_0_15_r_0_15[0][0] != cmd->obj0000)
           {
              pqr->c_0_15_r_0_15[0][0] = cmd->obj0000
              obj->isFound = true; //some common code for all ifs
           }

if (pqr->c_0_15_r_0_15[1][0] != cmd->obj0100)
           {
              pqr->c_0_15_r_0_15[1][0] = cmd->obj0100
              obj->isFound = true; //some common code for all ifs
           }

if (pqr->c_0_15_r_0_15[2][0] != cmd->obj0000)
           {
              pqr->c_0_15_r_0_15[2][0] = cmd->obj0200
              obj->isFound = true; //some common code for all ifs
           }

这里c_0_15_r_0_15[2][0]会经过[0][0]到[15][0]然后[0][1]到[15][1]等等在...

对于所有此类 if 条件场景,我将减少 100 条 if 语句。我们如何重构这样的代码?

首先,找到代码中的重复项。如您所知 - 以下方案已重复多次:

if (a != b)
{
    a = b;
    found = true;
}

所以-将其封装在函数中(如果有多种类型,则为模板:

template <typename Dst, typename Src>
inline void updateIfNeeded(Dst& dst, const Src& src, bool& wasNeeded)
{
    if (dst != src)
    {
        dst = src;
        wasNeeded = true;
    }
}

看看 - 它有什么帮助:

updateIfNeeded(abc->r16[0], cmd->r0m, obj->isFound);
updateIfNeeded(abc->r16[1], cmd->r1m, obj->isFound);
// ...
updateIfNeeded(pqr->c_0_15_r_0_15[0][0], cmd->obj0000, obj->isFound);
updateIfNeeded(pqr->c_0_15_r_0_15[1][0], cmd->obj0100, obj->isFound);
// ...

到目前为止 - 减少量很大 - 并且这段代码中发生的事情更具可读性。


我看到更多 - obj->isFound 重复了很多次 - 也许 - 这次在 class 中进行了一些封装:

class Updater
{
public:
    bool anyUpdateWasNeeded = false;

    template <typename Dst, typename Src>
    void  updateIfNeeded(Dst& dst, const Src& src)
    {
       if (dst != src)
       {
           dst = src;
           anyUpdateWasNeeded = true;
       }
   }
};

你看 - 不需要通过 obj->isFound 这么多次:

Updater upd;

upd.updateIfNeeded(abc->r16[0], cmd->r0m);
upd.updateIfNeeded(abc->r16[1], cmd->r1m);
// ...
upd.updateIfNeeded(pqr->c_0_15_r_0_15[0][0], cmd->obj0000);
upd.updateIfNeeded(pqr->c_0_15_r_0_15[1][0], cmd->obj0100);
// ...
obj->isFound = upd.anyUpdateWasNeeded;

坦率地说,此时我会考虑使用预处理器 - 我的意思是缩短所有这些数组更新 - 这是因为在左边你有数组 - 在右边你有许多名称相似的字段("indexed"名字...?)

但是使用预处理器是一种糟糕的风格 - 让我们尝试使用纯 C++ 更新数组:

class Updater
{
public:
    bool anyUpdateWasNeeded = false;

    template <typename Dst, typename Src>
    void  updateIfNeeded(Dst& dst, const Src& src);

    template <typename Dst, typename Src1, typename ...Src>
    void  updateArrayIfNeeded(Dst* dst, const Src1& src1, const Src& ...src)
    {
       updateIfNeeded(*dst, src1);
       updateArrayIfNeeded(dst + 1, src...);
   }
    template <typename Dst>
    void  updateArrayIfNeeded(Dst* dst) 
    {
        // nothing left
    }
};

所以 - 这是剩下的:

upd.updateArrayIfNeeded(abc->r16, cmd->r0m, cmd->r1m, ....);
upd.updateArrayIfNeeded(pqr->c_0_15_r_0_15[0], cmd->obj0000, cmd->obj0001, ...);
upd.updateArrayIfNeeded(pqr->c_0_15_r_0_15[1], cmd->obj0100, ...);
// ...
obj->isFound = upd.anyUpdateWasNeeded;

等等...

你可以把它放在一些函数中,首先:

template<typename Lhs, typename Rhs>
void flagSetIfNEq(Lhs & lhs, Rhs const & rhs, bool & flag) {
  if (lhs != rhs) {
    lhs = rhs;
    flag = true;
  }
}
// call it like
flagSetIfNEq(xyz->a, uvw->aa, obj->found)!

我假设您代码中的 found 类型为 bool

尽管如果您的代码中有“100 次”,您可能应该考虑进行更积极的重构。

并为该函数起一个更好的名字。