テンプレートパラメータ、#define、コードの重複
-
26-09-2019 - |
質問
次のようなコードがたくさんあります。
#define WITH_FEATURE_X
struct A {
#ifdef WITH_FEATURE_X
// ... declare some variables Y
#endif
void f ();
};
void A::f () {
// ... do something
#ifdef WITH_FEATURE_X
// ... do something and use Y
#else
// ... do something else
#endif
// ... do something
}
#defines をテンプレートパラメータに置き換えたいと思います。
template < int WITH_FEATURE_X > // can be 0 or 1
struct A;
ただし、A<0>::f() と A<1>::f() の A::f() のコードのほぼ全体を、パラメーターに依存する数行だけ複製したくありません。また、以前の #ifdef の代わりに関数を呼び出したくありません。一般的な解決策は何ですか?
解決
あなたが欲しいのは、D言語に存在する「static if」コマンドと同等だと思います。残念ながらそのような機能は C++ には存在しません。
コードの一部がリクエストの機能に応じて異なる場合、これらの部分は裸のアルゴリズムの一部ではないため、main 関数には属さないことに注意してください。したがって、そのような機能を関数で委任するオプションは良いもののように思えます。
編集
#ifdef ステートメントを使用して同じサブタスクを別の方法で実行する場合は、サブ関数を定義するのが適切です。コードは読みやすくなりますが、読みやすくなります。
これらがまったく異なるアクションに使用されている場合、コードはすでに乱雑になっています。そのために何かをする。
パフォーマンス上の問題が発生するのではないかと心配している場合は、コンパイラを信頼してください。
編集2
コードの最初の部分の答えを言うのを忘れていました。次のトリックを使用して、「機能」に応じてメンバーを追加または削除します。
namespace helper
{
template<int feature>
struct A;
template<>
struct A<0> { // add member variables for case 0 };
template<>
struct A<1> { // add member variables for case 1 };
}
template<int feature>
class A : private helper::A<feature>
{
// ... functions here
};
他のヒント
f
のロジックの重複を避けたい場合は、あなたは Template Methodパターン(いいえ、その種類 template
の
template <bool enabled>
class helper {
protected:
void foo() { /* do nothing */ }
};
template <>
class helper<true> {
protected:
Y y;
void foo() { /* do something with y */ }
};
struct A : private helper<WITH_FEATURE_X> {
void f() {
// common stuff
foo(); // optimized away when WITH_FEATURE_X is false
// more common stuff
}
};
一般的な解決策は、単に使用することです。 : - )
私は、共通のコードの重複のポイントを得ることはありません。 uはテンプレートパラメータを使用している場合uがちょうど(WITH_FEATURE_X)の場合で、あなたの#ifdefを交換します。 Uは、コンパイラによってコードの膨張について話しています。 私はあなたが任意の時点でA <0>またはA <1>のいずれかを使用することだろうと想定しています#ifdefの置き換えしようとしているので。私も、コンパイラによってコードの膨張が表示されないようにします。