2017-08-10 9 views
-3

最初の引数に基づいて2番目の引数の型を調整する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のために、私は任意の引数を使用したくないと case 3のために、私は引数型がfloatになりたい case 1ためのarg、整数になりたい:私はこのようなものを持っています。私はケース内でタイプをキャストすることができますが、それは悪いプログラミングのように思えます。この問題を解決するにはどうすればよいでしょうか?

+0

キャスト。できれば 'static_cast'を使ってください。 –

+0

'bar()'を呼んでいる人は、どのような型を望んでいるのかを知っていますか? – Galik

+0

'bar 'を呼び出すときに' arg'を 'int'または' float'にしたい場合はテンプレートやオーバーロードが必要でしょう。 – bbaldino

答えて

0

第1引数に応じて、第2引数の型を変えたいと思います。 C++は強力な型付き言語であり、コンパイル時に最初の引数の値を知る必要があることを意味します。これはテンプレート領域(私は幸せ)に私たちをもたらします。別の問題は、それを変更したい場合、2番目の引数を参照渡しする必要があるということです。

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に基づいて異なるように機能する必要がありますか?

古典的なprintfのような関数で使用されているvariadic argumentsの場合のように、パラメータ2の値を変更すると、コンパイル時に検出するのが困難なエラーの原因となります。実行時間を検出するのが難しくなります。

あなたは(私はまだあなたのデザインを再考をお勧めしますが)可変引数テンプレートを使用して、よりコンパイル時間フレンドリーなアプローチを検討するかもしれない:

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() 
関連する問題