用于固定类型集的显式实例化的单行代码

One-liner for explicit instantiation of fixed set of types

我有一套固定的ABCD四种类型,还有大量的class和函数模板适用于这些类型。

为了减少编译时间,我想将这些模板的定义放入 .cpp 文件中,并为这组固定类型显式实例化模板。 然而,显式实例化引入了很多样板代码,我想减少这些代码。 是否有一种优雅的方法可以显式实例化函数和 class 一组固定类型的模板?

下面是一些代码来说明问题:

#include <iostream>

class A { public: int foo() const { return 0; } };
class B { public: int foo() const { return 1; } };
class C { public: int foo() const { return 2; } };
class D { public: int foo() const { return 3; } };


template<typename T>
class SomeClass {
    /* could have a member variable of type A-D */
    T m_t;
    
    /* or several functions which take such a type */
    void printFoo(const T& t){
        std::cout << t.foo() << "\n";
    }
};


/* normal explicit instantiation */
//template class SomeClass<A>;
//template class SomeClass<B>;
//template class SomeClass<C>;
//template class SomeClass<D>;


/* or something with macros, but hopefully better than this: */

#define INSTANTIATE_FOR_ALL_TYPES \
INSTANTIATE_WITH(A) \
INSTANTIATE_WITH(B) \
INSTANTIATE_WITH(C) \
INSTANTIATE_WITH(D)

/* if this here could be one line instead of three, then you found the answer */
#define INSTANTIATE_WITH(TYPE) template class SomeClass<TYPE>;
INSTANTIATE_FOR_ALL_TYPES
#undef INSTANTIATE_WITH


int main(){
    return 0;
}

如果程序的设计不能确定类型不会改变,我就不会使用显式实例化。另外,我知道对于一次编译代码,编译时间不受显式实例化的影响。但是,当编写包含许多模板的测试时,并且经常进行重新编译时,效果非常明显。 如果还有其他选项可以缩短编译时间,我愿意接受。

目前,在有人找到更好的解决方案之前,下面的方法已经足够好了:

#define INSTANTIATE_FOR_ALL_TYPES(TYPE) template class SomeClass<TYPE>;
#include "instantiator.hpp"

instantiator.hpp的内容为

/* lack of a header guard is intentional */
INSTANTIATE_FOR_ALL_TYPES(A)
INSTANTIATE_FOR_ALL_TYPES(B)
INSTANTIATE_FOR_ALL_TYPES(C)
INSTANTIATE_FOR_ALL_TYPES(D)

#undef INSTANTIATE_FOR_ALL_TYPES

拼写错误和类似错误被预处理器捕获。这适用于以最少的代码重复实例化多个 functions/classes:

#define INSTANTIATE_FOR_ALL_TYPES(TYPE) \
template class SomeClass<TYPE>; \
template class AnotherClass<TYPE>; \
template void foo( const TYPE& );
#include "instantiator.hpp"

如果有人能发现这种方法的问题,欢迎提供反馈。但我更喜欢“这可能会在情况 y 下导致问题 x”而不是“宏是邪恶的”和“这不是你应该如何使用 #include”。