I'm writing a C++ library that contains a lot of function templates I want to explicitly instantiate and export for several type parameters. In my particular case, I have a lot of numeric function templates that I want to separately instantiate and compile for float
, double
, and long double
. They look something like this:
template <typename T>
T calculate_a(T x) { ... }
template <typename T>
T calculate_b(T x, T y) { ... }
// ...
If I have M function templates and N underlying types, then I have M*N explicit instantiations to type out. Is it possible to write these instantiations more concisely?
My current solution is to use a preprocessor macro that performs all instantiations for a given type:
#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);
However, this is suboptimal because it requires me to separately maintain another copy of each function template's signature. Also, if I want to do this in multiple translation units, then I need to separately maintain a list of underlying types in each. (Suppose that C++2a adds a long long double
type that I want to support; I'll have to add EXPLICITLY_INSTANTIATE(long long double);
to every file.)
Another possible approach is to gather up all of my functions into a (static-only) template class:
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>;
This solves the first problem of separately maintaining two copies of each signature, but requires me to change each call of calculate_a
into calculate::a<T>
. It doesn't address the second problem.