Constexpr против шаблона, функция pow

Я экспериментирую с новой особенностью С++ 11, constexpr. Если я хочу закодировать pow с шаблоном, я просто сделаю:

//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

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

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

Ответ 2

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

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

constexpr double powtest = pow(2.0, 5);

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