我正在编写一个 C++ 库,其中包含许多我想显式实例化和导出多个类型参数的函数模板。在我的特殊情况下,我有很多数字函数模板,我想分别为float
、double
和long double
. 它们看起来像这样:
template <typename T>
T calculate_a(T x) { ... }
template <typename T>
T calculate_b(T x, T y) { ... }
// ...
如果我有 M 个函数模板和 N 个基础类型,那么我就有 M*N 个显式实例化要输入。是否可以更简洁地编写这些实例化?
我当前的解决方案是使用一个预处理器宏来执行给定类型的所有实例化:
#define EXPLICITLY_INSTANTIATE(T) \
template T calculate_a<T>(T x); \
template T calculate_b<T>(T x, T y); \
// ...
EXPLICITLY_INSTANTIATE(float);
EXPLICITLY_INSTANTIATE(double);
EXPLICITLY_INSTANTIATE(long double);
然而,这是次优的,因为它需要我单独维护每个函数模板签名的另一个副本。此外,如果我想在多个翻译单元中执行此操作,那么我需要在每个翻译单元中单独维护一个基础类型列表。(假设 C++2a 添加了long long double
我想要支持的类型;我必须添加EXPLICITLY_INSTANTIATE(long long double);
到每个文件中。)
另一种可能的方法是将我的所有函数收集到一个(仅静态)模板类中:
template <typename T>
class calculate {
T a(T x) { ... }
T b(T x, T y) { ... }
};
template class calculate<float>;
template class calculate<double>;
template class calculate<long double>;
这解决了第一个问题,即分别维护每个签名的两个副本,但需要我将每个调用更改为calculate_a
into calculate::a<T>
。它没有解决第二个问题。