2013-08-20 3 views
10

Я экспериментирую с новой особенностью C++ 11, constexpr особенно. Если я хочу, чтобы закодировать Pow с шаблоном Я просто сделать: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; 
    } 
}; 

Теперь, если я называю функцию в мой код просто:

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

соответствующего узла будет (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 

Прекрасный код является встроенным.

Если знаю, что я ищу версию constexpr, у меня есть

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

Соответствующая сборка теперь:

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

где функция __Z # powIdET_RS0_m кажется определяют по

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

Итак, у вас есть идея, почему с constexpr функция не является встроенной и рассматривается как «внешняя "функция? Существует ли способ заставить встроенную функцию constexpr? Лучший.

+1

Почему аргумент вашего constexpr 'pow' not const? –

+0

Если я правильно интерпретирую дизассемблер моего g ++ 4.8.1 ('-O2'), он * делает * inline (и разворачивает рекурсию) вашу' pow' для небольших показателей, если показатель является литералом (известным при компиляции - время должно быть достаточным). Для более крупных экспонент (например, 10) он вводит функцию. В '-O3' он входит в линию даже для более высоких показателей (14). – dyp

+0

Себастьян: Я забыл^_ ^, DyP: интересно, я собираюсь попробовать новую версию компилятора –

ответ

1

inline - не более чем подсказка для компилятора. Он может делать все, что он предпочитает. Он содержит специфичные для компилятора вещи, такие как прагмы и __declspec, для принудительного включения или выключения вложения функции.

Может быть ссылка non const lvalue для версии constexpr. Так или иначе, вы должны просто передавать значение в сторону.

1

Это не ошибка для конкретного экземпляра шаблона функции constexpr, чтобы он не был действительно constexpr, если вы не пытаетесь использовать его в контексте, который требует постоянного выражения. Возможно, ваш экземплярный шаблон не является constexpr.

Чтобы узнать, сделайте следующее:

constexpr double powtest = pow(2.0, 5); 

Если компилятор жалуется, вы знаете, что есть что-то не так.

+0

Правильно, я знаю эту функцию. Ну, я больше искал переключение моей текущей реализации с помощью шаблона, constexpr, но с одним «динамическим» параметром –

+3

А, так что в основном вы обеспокоены тем, что компилятор ввел старую версию и не ввел новую. Это действительно интересно, тем более, что он, по-видимому, частично специализируется на функции constexpr. –

+0

Да, точно, встроенный снимите много управления стеком. Я должен внимательно прочитать норму и, возможно, задать вопрос о форуме GCC об этой функции. –