Предположим, что у меня есть функция вычисления длины вектора, которая имеет дополнительный параметр inc
(это говорит о расстоянии между соседними элементами).Простая реализация:
float calcLength(const float *v, int size, int inc) {
float l = 0;
for (int i=0; i<size*inc; i += inc) {
l += v[i]*v[i];
}
return sqrt(l);
}
Теперь calcLength
можно вызывать с двумя типами inc
параметров: когда inc
известен во время компиляции и когда нет.Я хотел бы иметь оптимизированную версию calcLength
для общих значений времени компиляции inc
(например, 1).
Итак, у меня было бы что-то вроде этого:
template <int C>
struct Constant {
static constexpr int value() {
return C;
}
};
struct Var {
int v;
constexpr Var(int p_v) : v(p_v) { }
constexpr int value() const {
return v;
}
};
template <typename INC>
float calcLength(const float *v, int size, INC inc) {
float l = 0;
for (int i=0; i<size*inc.value(); i += inc.value()) {
l += v[i]*v[i];
}
return sqrt(l);
}
}
Итак, это можно использовать:
calcLength(v, size, Constant<1>()); // inc is a compile-time constant 1 here, calcLength can be vectorized
или
int inc = <some_value>;
calcLength(v, size, Var(inc)); // inc is a non-compile-time constant here, less possibilities of compiler optimization
Мой вопрос: можно ли как-то сохранить оригинальный интерфейс и поставить Constant
/ Var
автоматически, в зависимости от типа (постоянная времени компиляции) inc
?
calcLength(v, size, 1); // this should end up calcLength(v, size, Constant<1>());
calcLength(v, size, inc); // this should end up calcLength(v, size, Var(int));
Примечание: это простой пример.В моей реальной проблеме у меня есть несколько функций, таких как calcLength
, и они большие, я не хочу, чтобы компилятор их встроил.
Примечание 2: Я также открыт для разных подходов,По сути, я хотел бы иметь решение, которое удовлетворяет следующим условиям:
- алгоритм указывается один раз (скорее всего, в шаблонной функции)
- , если я задаю
1
какinc
, создается специальная функция, и код, скорее всего, становится векторизованным - , если
inc
не является константой времени компиляции, общая функция вызывается - в противном случае (не-1константа времени компиляции): не имеет значения, какая функция вызывается