c ++的整数幂,模板元程序设计 [英] c++ power of integer, template meta programming

查看:160
本文介绍了c ++的整数幂,模板元程序设计的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个返回整数幂的函数。
请阅读fmuecke的解决方案
c ++中的整数幂



但是,我想把他的解决方案推广到任意类型T.
由于c ++ 11有constexpr,我想这是可能。



朴素,我尝试了像

 类T, 
inline constexpr T pow(const T x){
return pow< N-1>(x)* x;
}
template< class T>
inline constexpr T pow< T,1>(const T x){
return x;
}
template< class T>
Inline constexpr T pow< T,0>(const T x){
return 1;
}

实际上,此方法失败,因为不允许函数模板的部分专门化。 / p>

又一个问题。我听说编译器是否在编译时评估constexpr函数是否由编译器决定。
如何强制它为一般类型的计算。
我从某处读到一个最简单的整数常量的hack是包装在std :: integral_const :: value。

解决方案

解决方案使用递归:

  #include< iostream> 

template< class T>
inline constexpr T pow(const T base,unsigned const exponent)
{
//(下一行不需要括号)
return(exponent == 0)? 1:(base * pow(base,exponent-1));
}

int main()
{
std :: cout< pow(2,4):< pow(2,4)< std :: endl;
std :: cout<< pow(5,0):< pow(5,0)<< std :: endl;
}

Jeremy W. Murphy 建议/请求一个使用指数平方的版本:

  template< class T> 
inline constexpr T pow(const T base,unsigned const exponent)
{
//(下一行不需要括号)
return(exponent == 0)? 1:
(exponent%2 == 0)? pow(base,exponent / 2)* pow(base,exponent / 2):
base * pow(base,(exponent-1)/ 2)* pow
}






是由编译器确定的,不管是否在编译时对constexpr函数进行求值。



True,AFAIK。编译器不需要在编译时进行常数初始化,但是如果你使用constexpr函数的结果作为非类型模板参数,它必须在编译时计算结果。

  std :: cout< std :: integral_constant< int,pow(2,4)> :: value<< std :: endl; 

另请参阅使用 integral_constant 作为参数的方法 p>

以下是强制执行编译时评估的方法:

  #include< ; iostream> 
#include< type_traits>

//插入一个constexpr`pow'实现,例如。从上面的那个

模板<类型名T,T base,无符号指数>
using pow_ = std :: integral_constant< T,pow(base,exponent)>;

//宏==容易出错,你已被警告
#define POW(BASE,EXPONENT)(pow_< decltype(BASE),BASE,EXPONENT> :: value)

int main()
{
std :: cout< pow(2,4):< pow_< int,2,4> :: value< std :: endl;
std :: cout<< pow(2,4):< POW(2,4)<< std :: endl;
}






你downvote所以我可以提高我的回答。


I want to make a function which returns a power of integer. Please read the fmuecke's solution in power of an integer in c++ .

However, I want to generalize his solution to the arbitrary type T. Since c++11 has constexpr, I guess this is possible.

Naively, I tried something like,

template<class T, int N>
inline constexpr T pow(const T x){
    return pow<N-1>(x) * x;
}
template<class T>
inline constexpr T pow<T, 1>(const T x){
    return x;
}
template<class T>
inline constexpr T pow<T, 0>(const T x){
    return 1;
}

Actually this approach failed since the partial specialization for function template is not allowed.

And one more question. I heard that it is up to the compiler whether the constexpr function is evaluated in compile time or not. How do I force it to compute for general type. I read from somewhere that one of the simplest hack for integral consts is to wrap it in std::integral_const::value.

解决方案

Solution using recursion:

#include <iostream>

template<class T>
inline constexpr T pow(const T base, unsigned const exponent)
{
    // (parentheses not required in next line)
    return (exponent == 0) ? 1 : (base * pow(base, exponent-1));
}

int main()
{
    std::cout << "pow(2, 4): " << pow(2, 4) << std::endl;
    std::cout << "pow(5, 0): " << pow(5, 0) << std::endl;
}

Jeremy W. Murphy suggested/requested a version using exponentiation by squaring:

template<class T>
inline constexpr T pow(const T base, unsigned const exponent)
{
    // (parentheses not required in next line)
    return (exponent == 0)     ? 1 :
           (exponent % 2 == 0) ? pow(base, exponent/2)*pow(base, exponent/2) :
           base * pow(base, (exponent-1)/2) * pow(base, (exponent-1)/2);
}


"I heard that it is up to the compiler whether the constexpr function is evaluated in compile time or not."

True, AFAIK. The compiler isn't required to do constant-initialization at compile-time, but if you use the result of a constexpr function as a non-type template argument, it has to compute the result at compile-time.

std::cout << std::integral_constant<int, pow(2, 4)>::value << std::endl;

Also see the approach using integral_constant as parameter of pow in Andy Prowl's answer.

Here's how you can enforce compile-time evaluation:

#include <iostream>
#include <type_traits>

// insert a constexpr `pow` implementation, e.g. the one from above

template < typename T, T base, unsigned exponent >
using pow_ = std::integral_constant < T, pow(base, exponent) >;

// macro == error prone, you have been warned
#define POW(BASE, EXPONENT) (pow_ < decltype(BASE), BASE, EXPONENT > :: value)

int main()
{
    std::cout << "pow(2, 4): " << pow_<int, 2, 4>::value << std::endl;
    std::cout << "pow(2, 4): " << POW(2, 4) << std::endl;
}


Please leave a comment if you downvote so I can improve my answer.

这篇关于c ++的整数幂,模板元程序设计的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆