Я пишу библиотеку 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>
. Это не решает вторую проблему.
static_assert
, если тип шаблона не поддерживается. Например:template <typename T> T calculate() { static_assert( std::is_floating_point<T>::value, "Only supports floating points types" ); ... }
- person clcto   schedule 15.05.2018float
,double
иlong double
. Эти функции являются частью библиотечного компонента, который компилируется отдельно от основной программы, в которой они используются. Я отредактирую вопрос, чтобы уточнить это. - person David Zhang   schedule 15.05.2018