2010-03-04 11 views
5

Czy warto napisać kod jak poniżej, aby skopiować elementy tablicy:C++ METAPROGRAMOWANIE z szablonami porównaniu inline

#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; 
    } 

} //() 

czy lepiej użyć inlined funkcję?

Pierwszą wadą jest to, że nie można używać zmiennych w szablonie.

+2

Powinieneś po prostu użyć 'std :: copy'. Możesz być prawie pewien, że * to * wykorzystuje niektóre techniki metaprogramowania, aby przekazać kopiowanie pomiędzy tablicami int do memmove. – UncleBens

+1

Chryste, wolałabym spędzić 10 programików na programowanie w czasie życia niż spędzać więcej czasu na metaprogramowaniu w czasie kompilacji C++ :(. Jeśli musisz coś skopiować, musisz go skopiować, nie możesz oderwać się od niego, myśląc, że możesz to zrobić w czasie kompilacji tylko dlatego, że myślisz, że możesz zidentyfikować zmienne, które zostaną skopiowane. –

+0

@Hassan: W zależności od typów danych i dopasowania, różne strategie kopiowania mogą być odpowiednie, i może być możliwe znaczne przyspieszenie operacji. nie jest "tylko kopią". (Ale jak @UncleBens mówi, 'std :: copy' już to robi) – jalf

Odpowiedz

8

To nie lepiej. Przede wszystkim nie jest to czas kompilacji, ponieważ wykonujesz tutaj wywołania funkcji. Jeśli masz szczęście, kompilator zaznaczy je i zakończy pętlą, którą możesz napisać przy użyciu znacznie mniejszej ilości kodu (lub po prostu przy użyciu std::copy).

+3

+1 f * ck tak! ! – Tom

+2

To nie jest prawda. Rekursja jest w trakcie kompilacji, nie ma tu rekursji środowiska wykonawczego. Każda funkcja jest innej klasy i nie jest po prostu tą samą funkcją. Co by było jednak prawdą w Javie! – PierreBdR

+2

@PierreBdr, to prawda, że ​​za każdym razem zaimplementowana jest inna funkcja. Ale są to wywołania funkcji wykonywane w czasie wykonywania, a efekt jest taki, jakby wywołać tę samą funkcję w sposób rekursywny (w przeciwieństwie do * true * rekurencja czasu kompilacji ala '' static int const value = Class :: value + 1 ; '). Jedyną różnicą jest to, że stan końcowy może być oceniany w czasie kompilacji. Ale podobnie jak stan równoważnej pętli. –

0

Nie powinieneś tego robić. Szablony zostały wymyślone dla różnych celów, nie dla obliczeń, chociaż możesz to zrobić. Po pierwsze nie można używać zmiennych, drugie szablony będą generować olbrzymie nieużywane struktury podczas kompilacji, a trzecie: użycie for (int i = start; i <= end; i++) b[i] = a[i];

+1

Tak, szablony zostały wymyślone w innym celu, ale nie można po prostu zobrazować, ile książek i tuszów do książek użyto do tego drugiego nieinterwencyjnego użytku! – cibercitizen1

+0

Tak, nie zgłaszaj roszczeń dotyczących szablonów, których nie możesz uzasadnić. –

1

Ogólna reguła: używaj szablonów dla rzeczy znanych w czasie kompilacji, użyj podpowiadania dla rzeczy znanych w czasie wykonywania. Jeśli nie znasz rozmiaru tablicy w czasie kompilacji, nie używaj do tego szablonów.

0

To lepiej, ponieważ kontrolujesz i wymuszasz rozwijanie pętli przez siebie.

Pętla może być rozwijana przez kompilator w zależności od opcji optymalizujących ...

fakt, że kopiowanie z copy jest prawie najlepszy nie jest dobra odpowiedź ogóle, ponieważ rozwijanie pętli można zrobić cokolwiek jest obliczenie wykonane wewnątrz ...