Я пишу библиотеку 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
на calculate::a<T>
.Это не решает вторую проблему.