Включение инвариантного предположения в шаблонную функцию

Рассмотрим типичное конечно-разностное приложение:

// assuming T_size > 2
void process_T(double *T0, double *T, const int &T_size, bool periodic) {
for (int i = 0; i < T_size; ++i) {
double sum = 0;
double base = T0[i];
if (i > 0) sum += (T0[i-1]-base);
if (i < 0) sum += (T0[i+1]-base);
if (periodic) {
if (i == 0) sum += (T0[T_size-1]-base);
if (i == T_size-1) sum += (T0[0]-base);
} else {
if (i == 1 || i == T_size-1) sum += 0.5*(T0[i-1]-base);
if (i == 0 || i == T_size-2) sum += 0.5*(T0[i+1]-base);
}
T[i] = T0[i] + sum * 0.08; // where 0.08 is some magic number
}
}

Чек для periodic является инвариантным к циклу, но так как известно только во время выполнения, затраты на условную проверку возникают каждый раз. Я мог бы создать специализированную функцию, которая предполагает один из случаев, но было бы неудобно поддерживать общую базу, особенно в случае трехмерной задачи, где она вырастет до 8 функций (периодичность: нет, x, y, z, xy, xz, yz, xyz), чтобы рассмотреть все комбинации.

Можно ли решить эту проблему с помощью метапрограммирования?

P / S: может ли предсказатель ветви оптимизировать это соответственно?

3

Решение

Шаблоны могут иметь нетиповые параметры:

template <bool periodic>
void process_T(double *T0, double *T, const int &T_size)

Конечно, это подразумевает стоимость написания чего-то подобного на сайте вызовов:

bool periodicFunction = {whatever};
if (periodicFunction)
process_T<true>(...);
else
process_T<false>(...);
2

Другие решения

Да, вы могли бы иметь

enum Periodicity
{
PERIODICITY_NONE,
PERIODICITY_X,
PERIODICITY_Y
// etc
};

а потом

template <Periodicity P>
void process_T(double* T0, double* T, const int& T_size)
{
if (P == PERIODICITY_NONE) // ... do something
if (P == PERIODICITY_X) // ... do something else

// Common code
}

Любой достойный оптимизирующий компилятор сможет выполнить проверку во время компиляции и устранит любой мертвый код (g ++, кажется, делает это даже в -O0).

2

По вопросам рекламы [email protected]