最終的なバイナリにマージされるテンプレート化されたクラスのメンバ関数を持つ方法はありますか?私は、特定の機能をサポートし、それに依存して、メンバ関数の内部いくつかの追加のステップを必要とすることができるクラスがある:g ++:テンプレートメンバ関数のインスタンスをマージする
template <uint32_t features>
class Driver {
static bool set (uint32_t value) {
/* do something required for every feature */
if (features & Feature::A)
/* do special things if Feature::A */
/* do something required for every feature */
if (features & Feature::B || features & Feature::C)
/* do something special for either Feature::B or Feature::C */
return true;
}
/* more, similar methods */
};
後のコードで、私は、実際に応じDriver<Feature::A>::set
又はDriver<Feature::A | Feature::B>::set
等のコールを使用します利用可能な機能。これまでのところうまくいきますが、g++-5.4.0 -std=c++11 -O3
でコンパイルされたコードだけが同じメソッドをどのようにマージしていないのですか?このクラスには、共通の共通部分を持つ複数の関数があり、実際には最終的なバイナリのサイズが大きくなります。共通する部分についてはプライベート関数を使用すると、サイズのオーバーヘッドが減少しますが、私の意見では読むことのように友好的ではありませんが:特別のひとつに「早く出て」パスがある場合にも、これは、問題を紹介
template <uint32_t features>
class Driver {
static void _set_common_0 (value) {
/* do something required for every feature */
}
static bool set (uin32_t value) {
_set_common_0 (value);
if (features & Feature::A)
_set_special_0 (value);
_set_common_1 (value);
if (features & Feature::B || features & Feature::C)
_set_special_1 (value);
return true;
}
};
以前は単純なreturn
で行うことができましたが、現在はサブ機能からエスカレートされ、そのサブ機能の戻り値に応じてさらにチェックが行われます。
私は何をしたいですか?コンパイラはDriver<Feature::B>::set
とDriver<Feature::C>::set
のシンボルを(使用時に)発行しますが、コードで同一のコード位置を指していることを確認してください。どのように私はこれを行うことができる任意のアイデア? (好ましくは、新しい規格から機能を必要とC++ 11に滞在していない)
EDIT:(テンプレートインスタンスでここで生産)の同一の命令シーケンスをgcc
によって結合されていない理由を明確にするために、私は、疑問に思って。私の理解のために、-ftree-tail-merge
は少なくともそれらを同じ実装/コードシーケンス(e.q. Driver<Feature::B>::set
とDriver<Feature::C>::set
)へのジャンプで置き換えるべきです。
本当にクラステンプレートが必要ですか?これはテンプレートの使用方法ではないため、実行時にコンパイル時定数をチェックしています。 'if(features&Feature :: A)' –
は本当にコンパイル時定数ではありません。使用すべき機能は実行時依存であり、コンパイル時にはわかりません。実行時環境に依存して、私は 'Feature :: A'を使うことができますし、使用することはできません。 'Driver :: set'呼び出しは、直接発行されるのではなく、環境の検出された機能に依存して初期化中に割り当てられる関数ポインタによって呼び出されます。 –
Jonas