名前付きパラメーターBoost

C ++では、より柔軟な関数のパラメーター化メカニズムが必要になる場合があります。 たとえば、2つの必須パラメーターと多数のオプションを持つ関数があります。



bool foo(int important, int& pOut, int sometimes = 1, int occasionally = 2, int rarely = 3) { //... }
      
      





ここでの問題は次のようになります



  1. ユーザーは常にパラメーターの順序を混同します。そのタイプはほぼ同じであるため、コンパイラーは役に立ちません(2番目のパラメーターの場合を除く)。
  2. オプションのパラメータのうち、1つが最も頻繁に必要であり、そうでない場合は、デフォルト値を呼び出して呼び出しで明示的に設定する必要があります。 デフォルト値は異なるため、再び多くのエラーがあります
  3. 一部のパラメーターのデフォルト値が他のパラメーターに依存することを表す方法はありません。




これらの問題はさまざまな方法で解決できます。構造体をパラメーターとして渡す、関数のオーバーロードを使用する、または異なる名前の関数でさえも... Boostは別のソリューションを提供します。



これらは名前付きパラメーターです。 パラメータの順序に拘束されることはなくなりました。呼び出し時に意識的な名前を指定できるため、エラーの可能性が大幅に減少します。 追加のボーナスとして、他のデフォルト値を計算するときにいくつかのパラメーターを使用する機会があります。



例として、提案されたメカニズムを使用して関数fooを定義する方法を検討します(混乱しないように名前をnamedParametersFooに変更します)。 最初に、ブーストヘッダーファイルを含め、特別なマクロを使用してパラメーター名を決定します。 注意してください-句読点はありません。



 #include <boost/parameter.hpp> BOOST_PARAMETER_NAME(important) BOOST_PARAMETER_NAME(pOut) BOOST_PARAMETER_NAME(sometimes) BOOST_PARAMETER_NAME(occasionally) BOOST_PARAMETER_NAME(rarely)
      
      







次に、関数を設定します



 BOOST_PARAMETER_FUNCTION( (bool), namedParametersFoo, tag, (required (important, *) (in_out(pOut), *) ) (optional (sometimes, *, important * 2) (occasionally, *, 300) (rarely, *, 400) ) ) { //   }
      
      





コンマで区切られた4つのパラメーターがマクロに渡されます



  1. 戻りタイプ-括弧内に必要
  2. 機能名
  3. パラメータ付きの名前空間。 BOOST_PARAMETER_NAMEは自動的にタグに広告を配置します
  4. パラメータリスト


パラメータのリストには独自の構造があります。 また、句読点はほとんどないことに注意してください-即時パラメーターを決定するのはコンマだけです。



最初に必要なブロックがあります。 名前が示すように、必須パラメーターのリストが含まれています。 各パラメーターは括弧で囲む必要があります。 必須パラメーターを定義するには、その名前とタイプの制限を指定する必要があります。 この記事では、型制限メカニズムは考慮されていないため、アスタリスクのみを使用します。 このトピックの詳細については、 こちらをご覧ください



次に、オプションパラメータのブロックが続きます。 ここで、各パラメーターを定義するときに、デフォルト値を設定する追加の機会があります。 上記の例からわかるように、式で他のパラメーターを使用できます。



実際にはすべて。 関数は、「昔ながらの方法」の呼び出しをサポートします-通常のオプションのパラメーターで定義されているかのように。 つまり 獲得オプションのように



 bool newFoo(int important, int& pOut, int sometimes = important * 2, int occasionally = 2, int rarely = 3) { //... }
      
      





時々パラメータが重要に依存するため、 newFooはコンパイルされません。



つまり namedParametersFooを使用できます

  int s = 0; namedParametersFoo(1, s, 1, 1, 1); namedParametersFoo(1, s, 1, 1); namedParametersFoo(1, s, 1); namedParametersFoo(1, s);
      
      







しかし、それだけではありません! 名前付きパラメーターを使用することで、引数の順序と必要な不要なデフォルト値の両方から解放されます。 唯一の不便な点は、名前の先頭にアンダースコアを追加する必要があることです。



 namedParametersFoo(_sometimes = 1, _important = 111, _pOut = s);
      
      





この例では、新しいものは何ですか



  1. 可視性-数値1と111が正確に何を意味するかは明確であり、混乱/誤解の可能性が減少します
  2. 任意の順序-オプションのパラメーターが最初に書き込まれ、すべてが機能します


必要なパラメーターの位置を変更したり、オプションのパラメーターと組み合わせたりすることも可能になりましたが、すべてがコンパイル段階で制御され続けています。 次のコード



 namedParametersFoo(_sometimes = 1, _pOut = s);
      
      





収集されません-必要な_importantパラメーターが欠落しています



以上です。 このメカニズムは最も単純で明白ではないので、言語の標準的な手段で問題を回避できる場合は、そうすることをお勧めします。 さらに、名前付きブーストパラメーターを使用すると、コンパイル時間に悪影響を与える可能性があります。 しかし、すべての回避策が曲がっており、ブーストがプロジェクトですでに使用されている場合、間違いなくメリットがあります。



All Articles