2013-08-20 31 views
10

Eksperymentuję w szczególności z nową funkcją C++ 11, constexpr. Jeśli chcę zakodować pow z szablonu ja po prostu zrobić:constexpr versus template, pow function

//pow 
template<class T, std::size_t n> 
struct helper_pow{ 
    inline static T pow(T const& a){ 
     return a*helper_pow<T,n-1>::pow(a); 
    } 
}; 

//final specialization pow 
template<class T> 
struct helper_pow<T,0>{ 
    inline static T pow(T const& a){ 
     return 1; 
    } 
}; 

Teraz jeśli zgłoszę mojej funkcji do mojego kodu po prostu:

pow<double,5>(a) // where a is double 

odpowiedniego zespołu będzie (GCC 4.8. 0, -O2):

movapd %xmm0, %xmm1 
    movsd %xmm0, 24(%rsp) 
    mulsd %xmm0, %xmm1 
    movq %rbx, %rdi 
    mulsd %xmm0, %xmm1 
    mulsd %xmm0, %xmm1 
    mulsd %xmm0, %xmm1 

Dokładny kod jest wbudowany.

Jeśli wiemy szukam wersji constexpr mam

template <class T> 
inline constexpr T pow(T const& x, std::size_t n){ 
    return n>0 ? x*pow(x,n-1):1; 
} 

Odpowiedni montaż jest teraz:

movsd 24(%rsp), %xmm2 
    leaq 24(%rsp), %rdi 
    movl $4, %esi 
    movsd %xmm2, 8(%rsp) 
    call __Z3powIdET_RS0_m 

gdzie funkcja __Z # powIdET_RS0_m wydaje się zdefiniowanie przez

LCFI1: 
    mulsd %xmm1, %xmm0 
    movapd %xmm0, %xmm2 
    mulsd %xmm1, %xmm2 
    mulsd %xmm2, %xmm1 
    movapd %xmm1, %xmm0 
    ret 

Więc czy masz jakiś pomysł, dlaczego z constexpr funkcja nie jest wbudowana i należy ją uważać za "zewnętrzną "funkcja? Czy istnieje sposób na wymuszenie funkcji constexpr? Najlepsza.

+1

Dlaczego argument twojego constexpr 'pow' nie jest stały? –

+0

Jeśli poprawnie zinterpretuję demontaż mojego g ++ 4.8.1 ('-O2'), to * spowoduje * wstawienie (i rozwinięcie rekursji) twojego' pow' dla małych wykładników, jeśli wykładnik jest literałem (znany podczas kompilacji czas powinien wystarczyć). W przypadku większych wykładników (np. 10) wprowadza funkcję. W '-O3', jest on rozwijany nawet dla wyższych wykładników (14). – dyp

+0

Sebastian: Zapomniałem^_ ^, DyP: ciekawe, spróbuję nowej wersji kompilatora –

Odpowiedz

1

Inline to nic więcej niż podpowiedź dla kompilatora. Może robić, co chce. Istnieją specyficzne dla kompilatora rzeczy, takie jak pragmas i __declspec, które wymuszają lub wyłączają wbudowywanie funkcji.

Może być nieokreśloną wartością bezwzględną dla interakcji z wersją constexpr. Powinieneś po prostu przekazać wartość by pow.

1

Nie jest błędem dla konkretnego utworzenia szablonu funkcji constexpr, aby nie był naprawdę constexpr, o ile nie próbujesz używać go w kontekście, który wymaga stałego wyrażenia. Może twój utworzony szablon nie jest constexpr.

constexpr double powtest = pow(2.0, 5); 

Jeśli kompilator narzeka, wiesz, że jest coś nie tak:

Aby dowiedzieć się, to zrobić.

+0

Dobrze, znam tę funkcję. Cóż, bardziej szukałem przełączania mojej obecnej implementacji z szablonem, przez constexpr, ale z jednym "dynamicznym" parametrem –

+3

Ah, więc w zasadzie obawiasz się, że kompilator zaznaczył starą wersję i nie wstawił nowej. To naprawdę interesujące, zwłaszcza, że ​​pozornie częściowo specjalizuje się w funkcji constexpr. –

+0

tak dokładnie, wbudowany usuwa dużo zarządzania stosu. Powinienem uważnie przeczytać normę i być może zamieścić pytanie o forum GCC na temat tej funkcji. –