C++ 如何将代码重构为子例程,但允许提前退出?

C++ 如何将代码重构为子例程,但允许提前退出?,c++,refactoring,C++,Refactoring,在这段代码中有一个非常明显的重构机会 bool翻译::兼容代码(常量规则和规则, 常数标准::向量和尼科德斯) { bool包含=错误; //循环通过ni代码。 对于(std::vector::const_迭代器iter=nicodes.begin(); iter!=nicodes.end(); ++国际热核聚变实验堆(iter) { //与规则的ni代码匹配 if(rule.get_ni1()==*iter) { //如果存在匹配项,请检查它是否标记为包含或排除 const std::stri

在这段代码中有一个非常明显的重构机会

bool翻译::兼容代码(常量规则和规则,
常数标准::向量和尼科德斯)
{
bool包含=错误;
//循环通过ni代码。
对于(std::vector::const_迭代器iter=nicodes.begin();
iter!=nicodes.end();
++国际热核聚变实验堆(iter)
{
//与规则的ni代码匹配
if(rule.get_ni1()==*iter)
{
//如果存在匹配项,请检查它是否标记为包含或排除
const std::string flag=rule.get_op1();
//如果包含,则包含代码,除非稍后的规则将其排除
如果(flag==“INCLUDE”){INCLUDE=true;}
//如果排除,则明确排除代码
else if(flag==“EXCLUDE”){return false;}
}
if(rule.get_ni2()==*iter)
{
const std::string flag=rule.get_op2();
如果(flag==“INCLUDE”){INCLUDE=true;}
else if(flag==“EXCLUDE”){return false;}
}
if(rule.get_ni3()==*iter)
{
const std::string flag=rule.get_op3();
如果(flag==“INCLUDE”){INCLUDE=true;}
else if(flag==“EXCLUDE”){return false;}
}
if(rule.get_ni4()==*iter)
{
const std::string flag=rule.get_op4();
如果(flag==“INCLUDE”){INCLUDE=true;}
else if(flag==“EXCLUDE”){return false;}
}
if(rule.get_ni5()==*iter)
{
const std::string flag=rule.get_op5();
如果(flag==“INCLUDE”){INCLUDE=true;}
else if(flag==“EXCLUDE”){return false;}
}
}
包括退货;
}
我想把它变成这样:

bool Translations::compatibleNICodes(const Rule& rule, 
                                     const std::vector<std::string>& nicodes)
{
    bool included = false;

    // Loop through the ni codes.
    for(std::vector<std::string>::const_iterator iter = nicodes.begin();
        iter != nicodes.end();
        ++iter)
    {
        // Match against the ni codes of the rule
        included |= matchNICode(rule.get_ni1(), rule.get_op1);
        included |= matchNICode(rule.get_ni2(), rule.get_op2);
        included |= matchNICode(rule.get_ni3(), rule.get_op3);
        included |= matchNICode(rule.get_ni4(), rule.get_op4);
        included |= matchNICode(rule.get_ni5(), rule.get_op5);
    }
    return included;
}

bool Translations::matchNICode(const std::string& ni, 
                               const std::string& op)
{
    if(ni == *iter)
    {
        if(op == "INCLUDE"){ return true; }
        else if(op == "EXCLUDE"){ /*Return worse than false*/ }
    }
    return false;
}
bool翻译::兼容代码(常量规则和规则,
常数标准::向量和尼科德斯)
{
bool包含=错误;
//循环通过ni代码。
对于(std::vector::const_迭代器iter=nicodes.begin();
iter!=nicodes.end();
++国际热核聚变实验堆(iter)
{
//与规则的ni代码匹配
included |=匹配代码(rule.get_ni1(),rule.get_op1);
included |=匹配代码(rule.get_ni2(),rule.get_op2);
included |=匹配代码(rule.get_ni3(),rule.get_op3);
included |=匹配代码(rule.get_ni4(),rule.get_op4);
included |=匹配代码(rule.get_ni5(),rule.get_op5);
}
包括退货;
}
bool翻译::matchNICode(const std::string和ni,
const std::string和op)
{
如果(ni==*iter)
{
if(op==“INCLUDE”){return true;}
else if(op==“EXCLUDE”){/*返回比false更差的值*/}
}
返回false;
}
问题是,如果是exclude语句,我无法回避我希望提前退出的问题

请注意,我无法更改规则类的结构


有什么建议吗?

显然,如果您可以循环遍历
ni
op
规则的
成员,代码会更干净、更简单。如果你不能重构
规则
,也许你可以围绕它创建一个包装器来实现这个目标


如果您有一个使用这种代码的方法,我就不麻烦了。在我看来,只有通过几种类似的方法消除重复的代码,这才会有回报。

显然,如果您可以循环遍历
ni
op
规则
的成员,代码会更干净、更简单。如果你不能重构
规则
,也许你可以围绕它创建一个包装器来实现这个目标


如果您有一个使用这种代码的方法,我就不麻烦了。在我看来,只有用几种类似的方法消除重复的代码,这才会有回报。

下面是一种可能的重构,但我不确定这是否值得

定义NIU子句(ID)\ if(rule.get#ni#ID()==*iter)\ { \ const std::string flag=rule.get#u op#ID()\ 如果(flag==“INCLUDE”){INCLUDE=true;}\ else if(flag==“EXCLUDE”){return false;}\ } bool翻译::兼容代码(常量规则和规则, 常数标准::向量和尼科德斯) { bool包含=错误; //循环通过ni代码。 对于(std::vector::const_迭代器iter=nicodes.begin(); iter!=nicodes.end(); ++国际热核聚变实验堆(iter) { 第(1)条 第(2)条 第(3)条 第(4)条 第(5)条 } 包括退货; }
下面是一种可能的重构,但我不确定这是否值得

定义NIU子句(ID)\ if(rule.get#ni#ID()==*iter)\ { \ const std::string flag=rule.get#u op#ID()\ 如果(flag==“INCLUDE”){INCLUDE=true;}\ else if(flag==“EXCLUDE”){return false;}\ } bool翻译::兼容代码(常量规则和规则, 常数标准::向量和尼科德斯) { bool包含=错误; //循环通过ni代码。 对于(std::vector::const_迭代器iter=nicodes.begin(); iter!=nicodes.end(); ++国际热核聚变实验堆(iter) { 第(1)条 第(2)条 第(3)条 第(4)条 第(5)条 } 包括退货; }
bool Translations::compatibleNICodes(常量规则和规则),
常数标准::向量和尼科德斯)
{
bool包含=错误;
结构
{
规则(你得到)(你得到);;
规则_GET_OP GET_OP;
}方法tbl[]=
{
{&Rule::get_ni1,&Rule::get_op1},
{&Rule::get_ni2,&Rule::get_op2},
{&Rule::get_ni3,&Rule::get_op3},
{&Rule::get_ni4,&Rule::get_op4},
{&Rule::get_ni5,&Rule::
bool Translations::compatibleNICodes(const Rule& rule, 
                                     const std::vector<std::string>& nicodes)
{
    bool included = false;

    // Loop through the ni codes.
    for(std::vector<std::string>::const_iterator iter = nicodes.begin();
        iter != nicodes.end();
        ++iter)
    {
        // Match against the ni codes of the rule
        included |= matchNICode(rule.get_ni1(), rule.get_op1);
        included |= matchNICode(rule.get_ni2(), rule.get_op2);
        included |= matchNICode(rule.get_ni3(), rule.get_op3);
        included |= matchNICode(rule.get_ni4(), rule.get_op4);
        included |= matchNICode(rule.get_ni5(), rule.get_op5);
    }
    return included;
}

bool Translations::matchNICode(const std::string& ni, 
                               const std::string& op)
{
    if(ni == *iter)
    {
        if(op == "INCLUDE"){ return true; }
        else if(op == "EXCLUDE"){ /*Return worse than false*/ }
    }
    return false;
}
#define NI_CLAUSE(ID) \
        if(rule.get_ni ## ID() == *iter) \
        { \
            const std::string flag = rule.get_op ## ID(); \
            if(flag == "INCLUDE"){ included = true; } \
            else if(flag == "EXCLUDE"){ return false; } \
        }

bool Translations::compatibleNICodes(const Rule& rule, 
                                     const std::vector<std::string>& nicodes)
{
    bool included = false;

    // Loop through the ni codes.
    for(std::vector<std::string>::const_iterator iter = nicodes.begin();
        iter != nicodes.end();
        ++iter)
    {
        NI_CLAUSE(1)
        NI_CLAUSE(2)
        NI_CLAUSE(3)
        NI_CLAUSE(4)
        NI_CLAUSE(5)
    }
    return included;
}
bool Translations::compatibleNICodes(const Rule& rule,
                                     const std::vector<std::string>& nicodes)
{
    bool included = false;

    struct
    {
      RULE_GET_NI get_ni;
      RULE_GET_OP get_op;
    } method_tbl[] =
    {
      { &Rule::get_ni1, &Rule::get_op1 },
      { &Rule::get_ni2, &Rule::get_op2 },
      { &Rule::get_ni3, &Rule::get_op3 },
      { &Rule::get_ni4, &Rule::get_op4 },
      { &Rule::get_ni5, &Rule::get_op5 },
    };
    // Loop through the ni codes.
    for(std::vector<std::string>::const_iterator iter = nicodes.begin();
        iter != nicodes.end();
        ++iter)
    {
        for(size_t n = 0; n < 5 /* I am lazy here */; ++n)
        {
            if((rule.*(method_tbl[n].get_ni))() == *iter)
            {
                // If there's a match, check if the rule is include or exclude
                const std::string flag = (rule.*(method_tbl[n].get_op))();
                // If include, code is included unless a later rule excludes it
                if(flag == "INCLUDE"){ included = true; }
                // If exclude, code is specifically excluded
                else if(flag == "EXCLUDE"){ return false; }
            }
        }
    }
    return included;
}
bool Translations::compatibleNICodes(const Rule& rule, 
                                     const std::vector<std::string>& nicodes)
{
    bool included = false;

    try
    {
      // Loop through the ni codes.
      for(std::vector<std::string>::const_iterator iter = nicodes.begin();
          iter != nicodes.end();
          ++iter)
      {
        // Match against the ni codes of the rule
        included |= matchNICode(rule.get_ni1(), rule.get_op1);
        included |= matchNICode(rule.get_ni2(), rule.get_op2);
        included |= matchNICode(rule.get_ni3(), rule.get_op3);
        included |= matchNICode(rule.get_ni4(), rule.get_op4);
        included |= matchNICode(rule.get_ni5(), rule.get_op5);
      }
      return included;
    }
    catch (WorseThanFalseException& ex)
    {
      return false; // Or whatever you have to do and return
    }
}

bool Translations::matchNICode(const std::string& ni, 
                               const std::string& op)
{
    if(ni == *iter)
    {
        if(op == "INCLUDE"){ return true; }
        else if(op == "EXCLUDE"){ throw WorseThanFalseException(); } // Whatever this is
    }
    return false;
}
struct FUNCTOR : std::unary_function<bool, std::string const &>
{
  public:
    FUNCTOR(Rule const &r) : included(false), rule(r)
    {
    }
    // returns true if exluded
    bool operator()(std::string const &s)
    {
      static METHODS methods[] =
      {
        { &Rule::get_ni1, &Rule::get_op1 },
        { &Rule::get_ni2, &Rule::get_op2 },
        { &Rule::get_ni3, &Rule::get_op3 },
        { &Rule::get_ni4, &Rule::get_op4 },
        { &Rule::get_ni5, &Rule::get_op5 },
      };
      return(std::find_if(&methods[0], &methods[5], FUNCTOR2(rule, s, included)) != &methods[5]);
    }
    operator bool()
    {
      return(included);
    }
  private:
    struct METHODS
    {
      std::string (Rule::*get_ni)() const;
      std::string (Rule::*get_op)() const;
    };
    struct FUNCTOR2 : std::unary_function<bool, METHODS>
    {
      public:
        FUNCTOR2(Rule const &r, std::string const &s, bool &incl) : rule(r), str(s), included(incl)
        {
        }
        // return true if exluded
        bool operator()(METHODS m)
        {
          if((rule.*m.get_ni)() == str)
          {
            // If there's a match, check if the rule is include or exclude
            const std::string flag = (rule.*m.get_op)();
            // If include, code is included unless a later rule excludes it
            if(flag == "INCLUDE")
              included = true;
            // If exclude, code is specifically excluded
            else if(flag == "EXCLUDE")
            {
              included = false;
              return(true);
            }
          }
          return(false);
        }
      private:
        Rule const &rule;
        std::string const &str;
        bool &included;
    };
    Rule const &rule;
    bool included;
};

bool Translations::compatibleNICodes(const Rule& rule,
                                     const std::vector<std::string>& nicodes)
{
  FUNCTOR f(rule);
  std::find_if(nicodes.begin(), nicodes.end(), f);
  return(f);
}
class TriState
{
public:
  TriState(): mState(KO) {}

  bool isValid() const { return mState != FATAL; }

  bool ok() const { return mState == OK; }

  void update(std::string const& value,
              std::string const& reference,
              std::string const& action)
  {
    if (mState == FATAL) return;

    if (value == reference)
    {
      if (action == "INCLUDE") mState = OK;
      else if (action == "EXCLUDE") mState = FATAL;
    }
  }

private:
  typedef enum { OK, KO, FATAL } State_t;
  State_t mState;
};
TriState state;

for (const_iterator it = nicodes.begin(), end = nicodes.end();
     it != end && state.isValid(); ++it)
{
   state.update(*it, rule.get_ni1(), rule.get_op1);
   state.update(*it, rule.get_ni2(), rule.get_op2);
   state.update(*it, rule.get_ni3(), rule.get_op3);
   state.update(*it, rule.get_ni4(), rule.get_op4);
   state.update(*it, rule.get_ni5(), rule.get_op5);
}

return state.ok();
class Wrapper
{
public:
  Wrapper(Rule const& rule): mRule(rule) {}

  std::string const& get_ni(size_t i) const { switch(i) { ... } }
  std::string const& get_action(size_t i) const { switch(i) { ... } }

private:
  Rule const& mRule;
};
void update(std::string const& value, Wrapper wrapper, size_t index)
{
  if (mState == FATAL) return;

  if (value == wrapper.get_ni(index))
  {
    if (wrapper.get_action(index) == "INCLUDE") mState = OK;
    else if (wrapper.get_action(index) == "EXCLUDE") mState = FATAL;
  }
}
TriState state;
Wrapper wrapper(rule);

for (const_iterator it = nicodes.begin(), end = nicodes.end();
     it != end && state.isValid(); ++it)
{
  for (size_t index = 1; index != 6 && state.isValid(); ++index)
    state.update(*it, wrapper, index);
}

return state.ok();
bool Translations::compatibleNICodes(const Rule& rule, 
                                     const std::vector<std::string>& nicodes)
{
    bool included = false;

    // Loop through the ni codes.
    for(std::vector<std::string>::const_iterator iter = nicodes.begin();
        iter != nicodes.end();
        ++iter)
    {
        // Match against the ni codes of the rule
        if (!matchNICode(rule.get_ni1(), rule, &Rule::get_op1, included)) return false;
        if (!matchNICode(rule.get_ni2(), rule, &Rule::get_op2, included)) return false;
        if (!matchNICode(rule.get_ni3(), rule, &Rule::get_op3, included)) return false;
        if (!matchNICode(rule.get_ni4(), rule, &Rule::get_op4, included)) return false;
        if (!matchNICode(rule.get_ni5(), rule, &Rule::get_op5, included)) return false;
    }
    return included;
}

bool Translations::matchNICode(const std::string& ni, const Rule& rule, 
                               std::string (Rule::* const opfn)(), bool& included)
{
    if (ni == *iter) {
        const std::string& op = (rule.*opfn)();
        if (op == "INCLUDE") {
            included = true;
        }
        else if (op == "EXCLUDE") {
            return false;
        }
    }
    return true;
}