我正在开发一个有很多特质类型的项目。如果我在相同的代码库中编译每个特征,那么发布的二进制文件就会非常大。
我正在考虑使用宏为每个特定的特征构建一个二进制文件 - 从业务逻辑的角度来看,这是完全合理的。
然而,我意识到,如果我想减少代码库,我需要在每个模板cpp文件的末尾都有这个long if / 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 :(得分:0)
我不完全确定我的答案会解决问题的根本原因。但建议的解决方案至少可能看起来更“整洁”。
@JeffCharter http://localhost:4200背后的基本思想是有道理的,但我不喜欢将代码(在本例中为类型名称)嵌入到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;
}
此外,这里是proposal。
答案 1 :(得分: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