Шаблоны C ++ для создания нескольких версий функций с разными константами - PullRequest
1 голос
/ 28 октября 2010

Могу ли я использовать шаблон для создания нескольких экземпляров какой-либо функции, отличающихся только некоторым постоянным параметром? Количество альтернатив для этого параметра фиксировано. Например.

Я не хочу переписывать (где верхний в 1..32 в степени двух)

funct(param, int upper)
 {
  some_loops(..)
     some_heavy_code_fast_for_const_and_slow_for_variable(upper)
 }

в набор

funct_with_upper_is_1(param) // upper =1
 { manually_copied_code...heavy(1) }
funct_with_upper_is_2(param) // upper =2
 { manually_copied_code...heavy(2) }
funct_with_upper_is_4(param) // upper =4
 { manually_copied_code...heavy(4) }
funct_with_upper_is_8(param) // upper =8
 { manually_copied_code...heavy(8) }

но в шаблоне

template<int upper>
 funct_with_fixed_upper(param)
 { the_original_code....heavy(upper) }

, а затем

template<upper=1> funct_with_fixed_upper(param);
template<upper=2> funct_with_fixed_upper(param);
template<upper=4> funct_with_fixed_upper(param);
template<upper=8> funct_with_fixed_upper(param);

Возможно ли это с C ++ tempaltes?

== Подробный режим включен ==

У меня много C ++ файлов с таким кодом

function_typical(long long double ***A, long long double ***B, int const_1, int const_2)
// the type "long long double" here is very correct, this is extension of compiler
{

   for(int i=1;i<100000-1;i++)
      for(int j=1;j<100000-1;j++)
         for(int k=0;k<const_1;k++)
            for(int l=k;l<const_2;l++) {
                // some cray work with array like
                A[i][j][l-k]+=(B[i][j][l-k]+A[i+1][j][l-k]+A[i][j+1][l-k]-A[i-1][j][k]-A[i][j-1][l-k]/2.2)/88.3;
                if(A[i][j][l-k]>sin_lld(A[i][j-1][l-k])){B[i][j][l-k]=A[i][j][k]*4;}
            }
 }

Это только пример, но:

  • Я не могу поменять местами петли;
  • 2 внешних цикла, у i & j много итераций
  • 2 внутренних (вложенных), k & l имеют немного итераций, число которых передается в function_typical и их набор фиксирован, например, const_1 и const_2 - одна из пар: (2,3), (4,5), (3,5). Общее количество разрешенных пар меньше 10.

Проблема с этим кодом в том, что его скорость очень низкая. Если я исправлю const_1 и const_2 в этом коде для числовых констант, компилятор сделает большую работу по оптимизации (например, развернув все k и все l итераций, выполняя некоторую умную работу).

Но я физически не могу изменить каждую типичную функцию каждой пары (const_1 и const_2). Кроме того, постоянный пропагатор компилятора не может распространять константы набора информации функции (это сетевой сервер, и клиент выполняет выбор некоторого фиксированного набора пар const_1 и const_2 из фиксированного набора).

Так что я знаю во время компиляции все альтернативы пар. Но у меня нет шансов переписать каждую функцию вручную.

== подробный режим выключен ==

Заранее спасибо

Ответы [ 2 ]

5 голосов
/ 28 октября 2010

Абсолютно, это вполне возможно.Если вы берете int по шаблону, он действителен везде, где допустимо постоянное выражение.

template<int const_1, int const_2> function_typical(long long double ***A, long long double ***B)
// the type "long long double" here is very correct, this is extension of compiler
{

   for(int i=1;i<100000-1;i++)
      for(int j=1;j<100000-1;j++)
         for(int k=0;k<const_1;k++)
            for(int l=k;l<const_2;l++) {
                // some cray work with array like
                A[i][j][l-k]+=(B[i][j][l-k]+A[i+1][j][l-k]+A[i][j+1][l-k]-A[i-1][j][k]-A[i][j-1][l-k]/2.2)/88.3;
                if(A[i][j][l-k]>sin_lld(A[i][j][l-k])){B[i][j][l-k]=A[i][j][k]*4;}
            }
 }

Это должно перекомпилировать прямо, но вам придется изменить сайты вызовов.Кроме того, не забывайте, что шаблонный код должен иметь полный исходный код во всех единицах перевода и не может быть определен только в одном.

1 голос
/ 28 октября 2010

При условии, что ваш оригинальный шаблон:

template<int upper> 
  funct_with_fixed_upper(param)
  { the_original_code....heavy(upper) }

тогда, когда вы звоните, вы делаете это так:

 funct_with_fixed_upper<1>(param);
 funct_with_fixed_upper<2>(param);`

если вам нужно специализировать любой из них на основе константы, вы бы сделали это так:

 template<> funct_with_fixed_upper<1>(param) { // code here };

и, как уже говорили другие, это упростит поддержку кода, но не уменьшит размер скомпилированного кода, поскольку компилятор все равно расширит это ...

...