2010-03-04 6 views
5

Стоит ли писать код как следующее, чтобы скопировать элементы массива:C++ Метапрограммирование с шаблонами по сравнению встраивания

#include <iostream> 
using namespace std; 


template<int START, int N> 
struct Repeat { 
    static void copy (int * x, int * y) { 
    x[START+N-1] = y[START+N-1]; 
    Repeat<START, N-1>::copy(x,y); 
    } 
}; 

template<int START> 
struct Repeat<START, 0> { 
    static void copy (int * x, int * y) { 
    x[START] = y[START]; 
    } 
}; 



int main() { 


    int a[10]; 
    int b[10]; 

      // initialize 
    for (int i=0; i<=9; i++) { 
    b[i] = 113 + i; 
    a[i] = 0; 
    } 

      // do the copy (starting at 2, 4 elements) 
    Repeat<2,4>::copy(a,b); 

      // show 
    for (int i=0; i<=9; i++) { 
    cout << a[i] << endl; 
    } 

} //() 

или лучше использовать встраиваемую функцию?

Первым недостатком является то, что вы не можете использовать переменные в шаблоне.

+2

Вы должны просто использовать 'std :: copy'. Вы можете быть почти уверены, что *, который * использует некоторые методы метапрограммирования для пересылки копий между массивами int в memmove. – UncleBens

+1

Христос, я бы предпочел потратить 10 прожекторов программирования на жизнь, чем тратить больше времени на метапрограммирование времени компиляции C++ :(Если вам нужно что-то скопировать, вы должны его скопировать, вы не можете уйти от него, думая, что можете сделать он во время компиляции только потому, что вы считаете, что можете идентифицировать переменные, которые будут скопированы. –

+0

@ Хассан: В зависимости от типов данных и выравнивания могут быть подходящими различные стратегии копирования, и возможно, что можно быстро увеличить скорость работы. это не «просто копия». (Но, как пишет @UncleBens, 'std :: copy' уже делает это) – jalf

ответ

8

Это не лучше. Прежде всего, это не время компиляции, поскольку здесь вы вызываете вызовы функций. Если вам повезет, компилятор включит их и закончит цикл, который вы могли бы написать себе с гораздо меньшим количеством кода (или просто с помощью std::copy).

+3

+1 f * ck да! ! – Tom

+2

Это просто неправда. Рекурсия - это время компиляции, здесь нет рекурсии времени выполнения. Каждая функция имеет другой класс и является просто не той же самой функцией. То, что скажет, было бы справедливо для Java, хотя! – PierreBdR

+2

@PierreBdr, правда, каждый раз задействована другая функция. Но это вызовы функций, выполняемые во время выполнения, и эффект выглядит так, как если бы вы вызывали одну и ту же функцию рекурсивным образом (в отличие от * true * compile time recursion ala ''static int const value = Class :: value + 1 ; '). Единственное отличие состоит в том, что конечное условие может быть оценено во время компиляции. Но так же может быть и условие эквивалентного цикла. –

0

Вы не должны этого делать. Шаблоны были изобретены для разных целей, а не для расчетов, хотя вы можете это сделать. Во-первых, вы не можете использовать переменные, вторые шаблоны будут генерировать огромные неиспользуемые структуры при компиляции, а в-третьих: используйте for (int i = start; i <= end; i++) b[i] = a[i];

+1

Да, шаблоны были изобретены для разных целей, но вы просто не можете вообразить, сколько книг печатают и используют электронные чернила для этого второго использования без использования! – cibercitizen1

+0

Да, не претендуйте на шаблоны, которые вы не можете обосновать. –

1

Общее правило: используйте шаблоны для известных во время компиляции, используйте встроенную информацию для вещей, известных во время выполнения. Если вы не знаете размер вашего массива во время компиляции, не используйте шаблоны для него.

0

Это лучше, потому что вы сами контролируете и принудительно запускаете цикл.

петля может быть раскатали компилятором в зависимости от оптимизирующих опций ...

Тот факт, что копирование с copy почти лучший не хороший общий ответ, потому что разворачивания цикл может быть сделано все, что вычисление сделано внутри ...