5

C++での「優れた設計手法」について質問があります。私はC++11で数値ライブラリを作成しており、メタプログラミングやテンプレートベースの手法を数多く使用しています。しかし、私は非常に基本的な質問があります:

ブールフラグによってアクティブ化できるオプションを除いて、2つの非常に近い動作を持つことができる関数について考えてみます。開発者が設定/設定解除できるフラグのみを考慮し、実行時に設定/設定解除できるフラグは考慮しません。デザインには3つの可能性があります:


1)名前に明示的なオプションを指定して2つの関数を記述します。

myFunctionFlag1(...);
myFunctionFlag2(...); 

2)テンプレートパラメータを使用します:

template<bool Flag> myFunction(...);

3)可変パラメータを使用します:

myFunction(..., const bool flag);

優れた設計手法の観点から、どのソリューションが許容可能/許容不可能ですか?最良の解決策がある場合、それはどれですか、そしてその理由は何ですか?最悪の解決策がある場合、それはどれですか、そしてその理由は何ですか?

編集:考慮される関数の場合、実行時のオーバーヘッドは無視できると見なされる可能性があるため、これは最も重要なポイントではありません。

編集2:私は3つすべてが機能することを知っています。しかし、私のライブラリにはユーザーがいるので、信頼できる/優れたデザインが必要です。

オプション2は一般的ですか(私には良い妥協案のように思われるため)?

4

5 に答える 5

11

上記のどれでもない。ブールフラグは、コードの可読性にとってひどいものです。フラグ制御機能が十分に小さいため、単一の関数を使用するのが理にかなっている場合は、単一の関数を使用しますboolが、フラグのタイプとしては使用しないでください。代わりに、有用な名前を持つ列挙子で列挙を使用してください。

enum class MyFunctionMode { EnableFoo, DisableFoo };

void myFunction(..., MyFunctionMode mode);

このパターンにより、呼び出しサイトで関数に提供されているオプションを簡単に理解できます。フラグを使用して、複数のオプションを組み合わせることができます。

于 2012-10-03T19:31:52.073 に答える
2

オプション1を使用することをお勧めします。

コメント:

  1. 最もシンプルで明確です。実行時のオーバーヘッドはありません。
  2. このアプローチを使用するための十分な正当性(詳細が示されている場合はまだ存在する可能性があります)がわかりません。オプション1よりも複雑です。
  3. このバリアントには実行時のオーバーヘッドがあります。時間/CPU以外の重要なコードでも引き続き使用できます。関数が大きい場合(100行以上)、このバリアントはより魅力的になります。

私の2セント。

于 2012-10-03T19:24:20.550 に答える
0

あなたはあなたが知っている3つすべてを行うことができます。

void fun_that_does_stuff();
void fun_that_does_something_else();

template < bool F >
void fun_that_does_stuff_or_something();
template < >
void fun_that_does_stuff_or_something<true>() { fun_that_does_stuff(); }

... blah blah.
于 2012-10-03T19:29:18.607 に答える
0

最初のソリューションはコードを複製しますが、それは誰もやりたくないことです。

3番目のものは許容されますが、ifステートメントは実行時に評価され、時間の損失を意味します。

テンプレートは適切なようです。ifステートメントはeatherif (true)またはif (false)コンパイル時になり、コンパイラーは、ifステートメントがないかのように最適化します。

于 2012-10-03T19:26:36.447 に答える
0

重要なコードを複製することは最悪のオプションです。2つの関数が実際の興味深い関数にディスパッチするだけの場合は、それが正しいオプションである可能性があります。もちろん、2つの関数はテンプレート化されたバージョンにディスパッチできますが、違いが何であるか、または何ができるかをより正確に示すことがtrueできfalseます。

もう1つの懸念は、関数が実際にどのように使用されるかです。同じ構成またはフラグの選択を導き出すことができる構成を持つ関数から関数自体が呼び出される場合、異なる名前を使用すると、かなり煩わしくなり、保守できなくなります。条件付きで関数を呼び出す必要があります:

(flag? &myFunctionFlag1: &myFunctionFlag2)(...);

他の2つのバージョンのどちらを選択するかは、次の質問に当てはまります。チェックは重要ですか?含まれている場合は、テンプレートが唯一の選択肢です。そうでない場合は、どちらのバージョンも選択できます。匿名の投票でランタイムバージョンに投票することは間違いありません。些細なテンプレートを見せると、同僚の大多数の目がうっとりします。

于 2012-10-03T19:44:06.613 に答える