10

我正在试验 c++11 的新特性,尤其是 constexpr。如果我想用模板编写战俘,我会简单地做:

//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 函数的方法?最好的。

4

2 回答 2

1

inline 只不过是对编译器的提示。它可以为所欲为。它存在编译器特定的东西,如编译指示和 __declspec 来强制打开或关闭函数的内联。

可能是 constexpr 版本的非 const 左值引用干扰。无论如何,您应该只将值传递给战俘。

于 2013-08-20T12:01:06.763 回答
1

constexpr 函数模板的特定实例化不是真正的 constexpr 并不是错误,只要您不尝试在需要常量表达式的上下文中使用它。也许您的实例化模板不是 constexpr。

要找出答案,请执行以下操作:

constexpr double powtest = pow(2.0, 5);

如果编译器抱怨,你就知道有问题了。

于 2013-08-20T12:05:10.613 回答