2017-08-01 6 views
1

私は多くの形質タイプを持つプロジェクトに取り組んでいます。同じコードベースのすべての特性をコンパイルすると、リリースされたバイナリはかなり大きくなります。C++:どのように特定のバイナリ(実行可能ファイル)を作成するのですか?

私は、特定の特性ごとにバイナリを構築するためにマクロを使用することを考えています。ビジネスロジックの観点からは、これは完全に意味があります。

しかし、コードベースを削減したい場合、各テンプレートcppファイルの最後に/ elifファイルを置く必要があります。これは非常に退屈なことのように聞こえる。

この種の問題が発生したことがあるのではないかと疑問に思っていますが、ここで最もすばらしい解決策は何ですか?

#include "MyTraits.hpp" 
#include "Runner.hpp" 
int main(){ 
    #if defined USE_TRAIT_1 
    Runner<Trait1> a; 
    #elif defined USE_TRAIT_2 
    Runner<Trait2> a; 
    #elif defined USE_TRAIT_3 
    Runner<Trait3> a; 
    #endif 
    return 0; 
} 
+0

私は型定義のセットを定義し、一般的なテンプレート関数を呼び出すよりなり、それぞれが5つの異なるmain_ のcppファイルを、ちょうど持っています。 – SergeyA

+2

あなたの解決策は私によく見えます。それらのトンが多ければ、あなたのコードベースを解析してメイン関数とmakefile(または同様のもの)を生成するためのスクリプトを書くことができます。 'Runner USE_TRAITがあなたのmakeファイルにある場合 – JeffCharter

+1

具体的なやり方ではなく、' Runner a; 'を実行する方が簡単かもしれません。' -DUSE_TRAIT_1'でコンパイルするのではなく、 '-DTRAIT = Trait1'(使用しているビルドシステムに応じて適切に定義) – Justin

答えて

0

私の答えが問題の根本原因を解決するかどうかは完全にはわかりません。しかし、提案された解決法は、少なくとももう少し「きれいに」見えるかもしれません。

@JeffCharterのproposalの背後にある基本的な考え方は理にかなっていますが、コード(この場合はタイプ名)をメイクファイルに埋め込むことは嫌いです。だから私は、以下の目的を念頭において、それに少し詳しく説明:

  • を(メインの内容を確認します)ほとんどのマクロの使用を避けメイク
  • を汚染
  • 回避を理解し、短いと簡単に可能な範囲

私は、メイクファイルで定義できる単一の数値マクロを必要とする次の解決策になりました。 C++ 17のconstexpr ifを使用していることに注意してください。役立つ場合は、コンパイラがサポートしていることを確認してください。

constexpr int traitID = TRAIT_ID; // TRAIT_ID is a macro defined somewhere else. 

template <typename T> 
struct Wrapped // helper struct 
{ 
    using Type = T; 
}; 

auto trait() 
{ 
    // Although it may look not that different from macros, the main difference 
    // is that here all the code below gets compiled. 
    if constexpr (traitID == 1) 
     return Wrapped<Trait1>{}; 
    else if constexpr (traitID == 2) 
     return Wrapped<Trait2>{}; 
    else if constexpr (traitID == 3) 
     return Wrapped<Trait3>{}; 
    // add more cases if necessary 
} 

int main() // the contents of 'main' seems to have become more readable 
{ 
    using Trait = decltype(trait())::Type; 
    Runner<Trait> a; 
    return 0; 
} 

また、a live example at Coliruです。

0

明示的に特定のコンパイル単位でテンプレートをインスタンス化する場合は、extern templateというキーワードを使用する必要があります。

// Runner.hpp 
//define your template class 
template <class runner_trait> 
class Runner { 
... 
}; 

//This tells the compiler to not instanciate the template, 
// if it is encounterd, but link to it from a compilation unit. 
// If it is not found, you will get a linker errer. 
extern template Runner<Trait1>; 
extern template Runner<Trait2>; 
extern template Runner<Trait3>; 

Runner_trait1.cpp 

// the template class keyword tell the compiler to instanciate the template in this compilation unit. 
template class Runner<Trait1>; 

// The files for Runner_trait2.cpp and Runner_trait3.cpp look identical, 
// except for the trait after Runner 
関連する問題