2017-08-10 31 views
-3

我想編寫一個C++函數,它根據第一個參數調整第二個參數的類型。所以我有這樣的事情:在C++中更改參數類型的最佳做法

enum FtnType { FTN_A, FTN_B, FTN_C }; 

void bar(FtnType foo, const int arg = 0) 
{ 
    switch(foo) 
    { 
     case 0: 
      { 
       void ftnA(arg); 
       break; 
      } 
     case 1: 
      { 
       void ftnB(); 
       break; 
      } 
     case 2: 
      { 
       void ftnC(arg); 
       break; 
      } 
    } 
} 

現在對於case 0我想ARG是一個整數,case 1我不希望使用任何參數和case 3我想ARG類型爲浮動。我知道我可以在一個案例中投出類型,但這似乎是一個糟糕的編程習慣。什麼應該是解決這個問題的最好方法?

+0

石膏。 'static_cast',如果可以的話。 –

+0

調用'bar()'的人怎麼知道它會決定它想要的類型? – Galik

+0

我想你會需要一個模板或超負荷,如果你想'arg'是'int'或'float'當你打電話給''' – bbaldino

回答

0

在我看來,根據第一個參數,你想採取不同類型的第二個參數。 C++是一種強類型語言,這意味着您需要在編譯時知道第一個參數的值。這將我們帶入模板領域(我高興)。另一個問題是,如果您希望修改它,則需要通過引用傳遞第二個參數。

enum class FtnType { ftn_a, ftn_b, ftn_c }; 

template <FtnType type> struct Modify; 

template <> struct Modify<FtnType::ftn_a> 
{ 
    static auto modify(int& a) 
    { 
     ftnA(a); 
    } 
} 

template <> struct Modify<FtnType::ftn_b> 
{ 
    static auto modify() 
    { 
     ftnB(); 
    } 
} 

template <> struct Modify<FtnType::ftn_c> 
{ 
    static auto modify(float& a) 
    { 
     ftnC(a); 
    } 
} 

與用法:

int main() 
{ 
    int a = 24; 
    float f = 42.f; 

    Modify<FtnType::ftn_a>::modify(a); 
    Modify<FtnType::ftn_b>::modify(); 
    Modify<FtnType::ftn_c>::modify(f); 
} 

該作品以具有FtnType模板一個結構和各專門爲FtnType有不同的簽名靜態modify功能。

0

不知道我是否理解你的問題是正確的,但會超載這樣的工作?

void bar (int arg) 
{ 
    ftnA(arg); 
} 

void bar (float arg) 
{ 
    ftnC(arg); 
} 

void bar() 
{ 
    ftnB(); 
} 
0

你不需要所有這些功能和enum。只需使用重載函數:

void ftn(int arg) 
{ 
    std::cout << "I've got an int!" << std::endl; 
    // Do stuff which is in ftnA 
} 

void ftn(float arg) 
{ 
    std::cout << "I've got an float!" << std::endl; 
    // Do stuff which is in ftnC 
} 

void ftn() 
{ 
    std::cout << "I've got nothing! :(" << std::endl; 
    // Do stuff which is in ftnB 
} 

和簡單的調用

ftn(5); // Will print 'I've got an integer!' 
ftn(5.0f); // Will print 'I've got an float!' 
ftn();  // Will print 'I've got nothing! :(' 
0
enum class FtnType {FTN_A, FTN_B, FTN_C}; 

void bar(FtnType foo, const int arg = 0) { 
    [&] { 
     switch(foo) { 
      case FtnType::FTN_A: 
       return ftnA(arg); 
      case FtnType::FTN_B: 
       return ftnB(); 
      case FtnType::FTN_C: 
       return ftnC(static_cast<double>(arg)); 
     } 
    }(); 
} 

Live example

1

您正在嘗試混合編譯時一個有趣的組合和運行時的邏輯。雖然您可能通過使用模板來實現某些功能,但通過將參數1指定爲編譯時已知值,我並不完全確定這是可取的。

你要求一個最佳實踐,老實說,我認爲最好的做法是退後一步,重新考慮你的設計。爲什麼你需要你的功能根據參數1工作如此不同?

如果您要更改參數2的值(例如在經典的printf中使用的variadic arguments類似的函數),那麼您將有一個在編譯時很難檢測到的錯誤源,甚至難以檢測運行時間。

你可以使用可變參數模板(雖然我還是建議重新考慮你的設計)考慮一個更編譯時間友好的方法:

template <typename F, typename... T> 
void bar(F func, T... params) { 
    func(params...); 
} 

對這種做法的好處,是不小心傳遞錯誤的參數類型,或參數個數,會導致編譯時錯誤。這種方法將要求您知道在bar之外執行的功能。

void test1(int a, double b, char c) { 
    std::cout << "test1(" << a << ", " << b << ", " << c << ")\n"; 
} 

void test2() { 
    std::cout << "test2()\n"; 
} 

int main() { 
    bar(test1, 1, 2.1, 'c'); 
    bar(test2); 
    return 0; 
} 

這個測試代碼可以在這裏找到運行:http://ideone.com/vU30qn和輸出:

test1(1, 2.1, c) 
test2()