2017-08-01 75 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