簡體   English   中英

最佳實踐C ++元編程:邏輯流程

[英]Best practice C++ metaprogramming: logic flow

也許我被Ruby寵壞了,但是在我看來,如果我有兩個使用相同基本邏輯(但細節有所不同)的函數,則只需要編寫一次邏輯即可,因此,我只需要將代碼維護在一個地方。

這是基本邏輯,我在許多不同的功能中都重復使用了這些邏輯。 更改的部分標記為A,B,C,D,E和F。

  if (recursions) {
    while (lcurr || rcurr) {

      if (!rcurr || (lcurr && (lcurr->key < rcurr->key))) {
        // A
        lcurr   = lcurr->next;
      } else if (!lcurr || (rcurr && (rcurr->key < lcurr->key))) {
        // B
        rcurr   = rcurr->next;
      } else { // keys are == and both present
        // C
        lcurr   = lcurr->next;
        rcurr   = rcurr->next;
      }
    }
  } else {
    while (lcurr || rcurr) {
      if (!rcurr || (lcurr && (lcurr->key < rcurr->key))) {
        // D
        lcurr         = lcurr->next;
      } else if (!lcurr || (rcurr && (rcurr->key < lcurr->key))) {
        // E
        rcurr         = rcurr->next;
      } else { // keys == and both left and right nodes present
        // F
        lcurr         = lcurr->next;
        rcurr         = rcurr->next;
      }
    }
  }

函數的返回值也可能不同。 如果可能的話,我希望能夠在其他地方也有其他邏輯。

我意識到這可以通過C宏來完成,但是它們似乎並不是特別可維護。 我還意識到,如果我的矩陣類型使用嵌套的STL列表,這可能會更容易。 但是C ++ 11(或舊的C ++)中是否有任何功能只能將此邏輯編寫一次? 可以用lambda做到這一點嗎?

我看到的完成方式是編寫回調函數。 因此,您只需編寫一次邏輯部分,就像在第二個文本塊中一樣。 您還將定義函數A,B,C,D,E和F。

在邏輯函數中,您將同時傳入所需的參數和指向回調函數的指針。 然后,在邏輯函數中,您將調用這些回調並將其需要的參數傳遞給它們。

老實說,這似乎最終將需要更多工作。 您將為邏輯維護一個真相,但函數指針可能會非常麻煩,並且會降低代碼的可讀性。

為了提供盡可能多的信息,示例:

int addTwoNumbers(int a, int b) { //A simple adding function
   return a + b; 
}

int subtractTwoNumbers(int a, int b) { //A simple subtracting function
    return a - b;
}

/*
 * This is the fun one. The first argument is a pointer to a function. The other 
 * arguments are the numbers to do math with. They aren't as important.
 * The important part is that, so long as the function declaration matches the one here
 * (so a function that returns an int and takes in two ints as arguments) it can be
 * used by this function
 */
void math(int (*mathFunc)(int, int), int one, int two) {
    cout << *mathFunc(one, two);
}

int main(int argc, char* argv[]) {
    int whichMath = 0; //Assume 1 is add, 2 is subtract
    if(whichMath == 1) {
        math(&addTwoNumbers, 5, 6); //we're going to add 5 and 6
    } else {
        math(&subtractTwoNumbers, 5, 6); // we're going to subtract 5 and 6
    }
}

如果那沒有道理,那么歡迎您加入我們中使用函數指針而奮斗的大軍。 同樣,我想說的是您應該只編寫兩個單獨的函數,因為您可以看到這將變得多么丑陋。

作為免責聲明,我尚未編譯此代碼。 我在工作,這些機器上沒有c ++編譯器。

我過去曾大量使用此站點作為功能指針的參考: http : //www.newty.de/fpt/fpt.html#defi

好的,一種解決方案是提取一些冗余代碼並將其放入模板中,例如

  template<T1, T2, T3>
  bool TESTKEYS(T1 lcurr, T2 rcurr, T3 actor)
  {
    while (lcurr || rcurr) {
      if (!rcurr || (lcurr && (lcurr->key < rcurr->key))) {
        if (actor.TestLeft(....)) return false;
        lcurr         = lcurr->next;
      } else if (!lcurr || (rcurr && (rcurr->key < lcurr->key))) {
        if (actor.TestRight(....)) return false;
        rcurr         = rcurr->next;
      } else { // keys == and both left and right nodes present
        if (actor.TestBoth(....)) return false;
        lcurr         = lcurr->next;
        rcurr         = rcurr->next;
      }
    }
    return true;
  }

您將需要自己決定要為TestLeft等使用哪些參數。

template<typename A, typename B, typename C>
void compute (/*some parameters */)
{
   if (recursions) {
     while (lcurr || rcurr) {
       if (!rcurr || (lcurr && (lcurr->key < rcurr->key))) {
         auto aResult = A (lcurr, rcurr);
        lcurr   = lcurr->next;
       } else if (!lcurr || (rcurr && (rcurr->key < lcurr->key))) {
        auto bResult = B (lcurr, rcurr);
       } // ... and so on
       C (aResult, bResult);
    } // ... etc
} 

要調用compute ,你需要寫你想傳遞下來的地方您的A到F占位符的 實際工作在每個類的operator()成員函數中完成。

class A1 {
  public:
    double operator() (SomeType t1, SomeType t2) {
      // do work
    }
};

class A2 {
  public:
    int operator() (SomeType t1, SomeType t2) {
      // do work
    }
};

class B1 {
  public:
    char* operator() (SomeType t1, SomeType t2) {
      // do work
    }
};

class B2 {
  public:
    SomeClass* operator() (SomeType t1, SomeType t2) {
      // do work
    }
};

class C1 {
  public:
    int operator() (double t1, char* t2) {
}

class C2 {
  public:
    int operator() (int t1, SomeClass* t2) {
}

compute<A1, B1, C1>(whatever);
compute<A2, B2, C2>(whatever);

請注意,A1和B1返回類型如何與C1參數匹配,對於A2,B2和C2同樣。

auto需要C ++ 11,如果無法使用它,則必須做一些額外的工作:

class A1 {
  public:
    typedef double result_type;
    double operator() (SomeType t1, SomeType t2) {
      // do work
    }
};

和內部compute

             typename A::result_type aResult = A (lcurr, rcurr);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM