Metaprogramowanie - silnia, konkretyzacja.

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?

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.

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 ;)

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.com/2012/12/metaprogramowanie-cz2-polimorfizm.html

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