Metaprogramowanie - silnia, konkretyzacja.

Odpowiedz Nowy wątek
2011-09-16 22:58
cppppppp
0

mam sobie szablon funkcji:

template<unsigned n>
long long unsigned silnia()
{
    return silnia<n-1>()*n;
}

template<>
long long unsigned silnia<0>()
{
    return 1 ;
}

//gdzieś tam w kodzie:
std::cout<<silnia<5>()<<"\n";

myślałem, że skoro jest to metaprogramowanie, kompilator skonkretyzuje mi to wywołanie po prostu do:

return 120 ;

jednak nie:


_Z6silniaILj5EEyv:
.LFB961:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    pushl   %ebx
    subl    $4, %esp
    .cfi_offset 3, -12
    **call  _Z6silniaILj4EEyv**
    imull   $5, %edx, %ecx
    imull   $0, %eax, %ebx
    addl    %ebx, %ecx
    movl    $5, %ebx
    mull    %ebx
    addl    %edx, %ecx
    movl    %ecx, %edx
    addl    $4, %esp
    popl    %ebx
    popl    %ebp
    ret
    .cfi_endproc

(...)

_Z6silniaILj4EEyv:
.LFB965:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    subl    $8, %esp
    **call  _Z6silniaILj3EEyv**
    shldl   $2, %eax, %edx
    sall    $2, %eax
    leave
    ret
    .cfi_endproc

(...)

_Z6silniaILj3EEyv:
.LFB968:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    pushl   %ebx
    subl    $4, %esp
    .cfi_offset 3, -12
    **call  _Z6silniaILj2EEyv**
    imull   $3, %edx, %ecx
    imull   $0, %eax, %ebx
    addl    %ebx, %ecx
    movl    $3, %ebx
    mull    %ebx
    addl    %edx, %ecx
    movl    %ecx, %edx
    addl    $4, %esp
    popl    %ebx
    popl    %ebp
    ret
    .cfi_endproc

(...)

_Z6silniaILj2EEyv:
.LFB971:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    subl    $8, %esp
    **call  _Z6silniaILj1EEyv**
    shldl   $1, %eax, %edx
    addl    %eax, %eax
    leave
    ret
    .cfi_endproc

(...)

_Z6silniaILj1EEyv:
.LFB973:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    **call  _Z6silniaILj0EEyv**
    popl    %ebp
    ret
    .cfi_endproc

(...)

_Z6silniaILj0EEyv:
.LFB958:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    **movl  $1, %eax**  # WRESZCIE
    movl    $0, %edx
    popl    %ebp
    ret
    .cfi_endproc

czemu tak jest? jaki w takim razie jest sens metaprogramowania z użyciem szablonów funkcji, skoro w miejscu wywołania silnia<200>() tak naprawdę tworzy się 200 funkcji wywołujących siebie nawzajem?

A z optymalizacjami włączonymi kompilujesz? - Rev 2011-09-16 23:03
Zrobiłem test z printfem oraz -O3 i wyszło movl $120, 4(%esp). - Zjarek 2011-09-16 23:09

Pozostało 580 znaków

2011-09-16 23:24
0

Ale tym kodem przecież generujesz n funkcji. Zobacz na Wikipedię: http://en.wikipedia.org/wiki/Template_metaprogramming tam jest używany enum, czyli zbiór statycznych stałych, a więc obliczanych z definicji w czasie kompilacji.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.

Pozostało 580 znaków

2011-09-17 14:49
1

A weź sprawdź to:

 template < int N >
struct silnia {
    static int const value = N*silnia<N-1>::value;
};

template < >
struct silnia<0> {
    static int const value = 1;
};

To podejście jest zazwyczaj stosowane ;)

edytowany 1x, ostatnio: Atael, 2011-09-17 14:50

Pozostało 580 znaków

2013-01-09 20:27
dab.prog
0

Metaprogramowanie to nie tylko wyliczanie wartości w czasie kompilacji (tojest raczej nie często spotykane zastosowanie) polecam poczytać o boost mpl lub http://dabprograming.blogspot[...]amowanie-cz2-polimorfizm.html

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0