2017-08-01 76 views
1

我的工作,有很多特質類型的項目。如果我在相同的代碼庫中編譯每個特徵,則釋放的二進制文件將會很大。C++:如何爲每個特質製作特定的二進制文件(可執行文件)?

我正在考慮使用宏來從商業邏輯角度就爲每個特定性狀的二進制---,這非常有意義。

但是,我意識到,如果我想減少代碼庫,我需要有這樣長的if/elif的堆在每個模板CPP文件的末尾。這聽起來像是一件非常乏味的事情。

我想知道,如果你也遇到這樣的問題之前,這裏什麼是最整齊的解決方案?

#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(或類似的)。你也可以這樣做,也許'亞軍其中USE_TRAIT是在你的make文件 – JeffCharter

+1

而不是你做的具體方式,它可能會更容易,而不是做'亞軍一個;'和,而不是隻用'-DUSE_TRAIT_1'編譯,你'do do -DTRAIT = Trait1'(對於你正在使用的任何構建系統都適當定義) – Justin

回答

0

我不完全確定我的答案將解決問題的根本原因。但建議的解決方案可能至少看起來更「整潔」一些。

@JeffCharter提供的proposal背後的基本思想很有意義,但我不喜歡將代碼(在這種情況下鍵入名稱)嵌入到makefile中的想法。所以,我就可以闡述一下,在考慮了以下目標:

  • 製作的內容main()的短期和易於理解
  • 避免污染的makefile
  • 避免宏觀使用最可能的程度

我結束了以下解決方案,它需要一個可以在makefile中定義的數字宏。請注意它使用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